2016-04-26 13 views
1

Ich versuche, ein Array nach mehreren Eigenschaften zu sortieren, aber das Problem ist, dass mein Array multidimensional ist. Zur Zeit habe ich dieses Jahr:Sortieren eines mehrdimensionalen Arrays nach mehreren Eigenschaften

// Private function to get the value of the property 
var _getPropertyValue = function (object, notation) { 

    // Get all the properties 
    var properties = notation.split('.'); 

    // If we only have one property 
    if (properties.length === 1) { 

     // Return our value 
     return object[properties]; 
    } 

    // Loop through our properties 
    for (var property in object) { 

     // Make sure we are a property 
     if (object.hasOwnProperty(property)) { 

      // If we our property name is the same as our first property 
      if (property === properties[0]) { 

       // Remove the first item from our properties 
       properties.splice(0, 1); 

       // Create our new dot notation 
       var dotNotation = properties.join('.'); 

       // Find the value of the new dot notation 
       return _getPropertyValue(object[property], dotNotation); 
      } 
     } 
    } 
}; 

// Create a service 
var service = { 

    // Sorts our products 
    sort: function (products, notation) { 

     notation = notation || 'details.title'; 

     // Call sort 
     products.sort(function (a, b) { 

      // Get our values 
      var aValue = _getPropertyValue(a, notation), 
       bValue = _getPropertyValue(b, notation); 

      console.log(bValue); 

      // If our attribute name is not the same as the second attribute 
      if (aValue <= bValue) { 

       // Return -1 
       return -1; 
      } 

      // Otherwise return 1 
      return 1; 
     }); 
    } 
}; 

// Return our service 
return service; 

Und das ist ein Element aus dem Array (Produkte)

{ 
    "id": 1, 
    "gtin": "8714574627946|4549292038446", 
    "productId": "0592C022", 
    "make": "Canon", 
    "model": "750D + EF-S 18-55mm", 
    "expert": false, 
    "sponsored": false, 
    "attributes": { 
     "id": 1, 
     "compatibleMemory": "SD, SDHC, SDXC\"", 
     "whiteBalance": "ATW, Cloudy, Custom modes, Daylight, Flash, Fluorescent L, Shade, Tungsten\"", 
     "sceneModes": "Food, Landscape, Sports\"", 
     "shootingModes": "", 
     "photoEffects": "", 
     "cameraPlayback": "Movie, Single image, Slide show\"", 
     "tripod": false, 
     "directPrinting": false, 
     "colour": "Black", 
     "picture": { 
      "id": 1, 
      "megapixel": "24.2 MP", 
      "type": "SLR Camera Kit", 
      "sensorType": "CMOS", 
      "maxResolution": "6000 x 4000 pixels", 
      "resolutions": "3984x2656, 2976x1984, 1920x1280, 720x480, 5328x4000, 3552x2664, 2656x1992, 1696x1280, 640x480, 6000x3368, 3984x2240, 2976x1680, 1920x1080, 720x480, 4000x4000, 2656x2656, 1984x1984, 1280x1280, 480x480\"", 
      "stablizer": true, 
      "location": "Lens", 
      "supportedAspectRatios": "2.9 cm", 
      "totalMegapixels": "24.7 MP", 
      "formats": "JPG" 
     }, 
     "video": { 
      "id": 1, 
      "maxResolution": "1920 x 1080 pixels", 
      "resolutions": "640 x 480, 1280 x 720, 1920 x 1080 pixels\"", 
      "captureResolution": "", 
      "frameRate": "", 
      "fullHD": true, 
      "supportedFormats": null 
     }, 
     "audio": { 
      "id": 1, 
      "supportedFormats": "" 
     }, 
     "battery": { 
      "id": 1, 
      "powerSource": "Battery", 
      "technology": "Lithium-Ion (Li-Ion)", 
      "life": "", 
      "type": "LP-E17" 
     }, 
     "dimensions": { 
      "id": 1, 
      "width": "", 
      "depth": "7.78 cm", 
      "height": "10.1 cm", 
      "weight": "", 
      "weightIncludingBattery": "555 g" 
     }, 
     "display": { 
      "id": 1, 
      "type": "LCD", 
      "diagonal": "7.62 cm (3\"\")\"", 
      "resolution": "1040000 pixels" 
     }, 
     "exposure": { 
      "id": 1, 
      "isoSensitivity": "100, 6400, 12800, Auto\"", 
      "mode": "Auto, Manual\"", 
      "correction": "�5EV (1/2; 1/3 EV step)", 
      "metering": "Centre-weighted, Evaluative (Multi-pattern), Partial, Spot\"", 
      "minimum": 100, 
      "maxiumum": 12800 
     }, 
     "flash": { 
      "id": 1, 
      "modes": "Hi-speed sync, Red-eye reduction\"", 
      "exposureLock": true, 
      "rangeWide": "", 
      "rangeTelephoto": "", 
      "rechargeTime": "", 
      "speed": "1/200" 
     }, 
     "focusing": { 
      "id": 1, 
      "focus": "TTL-CT-SIR", 
      "adjustment": "", 
      "autoFocusModes": "", 
      "closestDistance": "0.25 m", 
      "normalRange": "", 
      "macroRangeTelephoto": "", 
      "macroRangeWide": "", 
      "autoModeTelephoto": "", 
      "autoModeWide": "" 
     }, 
     "interface": { 
      "id": 1, 
      "pictBridge": true, 
      "usbVersion": "2.0", 
      "usbType": "", 
      "hdmi": true, 
      "hdmiType": "Mini" 
     }, 
     "lens": { 
      "id": 1, 
      "focalLength": "18 - 55 mm", 
      "minimumFocalLength": "2.9 cm", 
      "maximumFocalLength": "8.8 cm", 
      "minimumAperture": "3.5", 
      "maximumAperture": "38", 
      "lensStructure": "13/11", 
      "zoom": { 
       "id": 1, 
       "optical": "", 
       "digital": "", 
       "extraSmart": "", 
       "combined": "" 
      } 
     }, 
     "network": { 
      "id": 1, 
      "wiFi": false, 
      "wiFiStandards": "", 
      "nfc": false 
     }, 
     "shutter": { 
      "id": 1, 
      "fastestSpeed": "1/4000 s", 
      "slowestSpeed": "30 s" 
     } 
    }, 
    "details": { 
     "id": 1, 
     "title": "Canon EOS 750D + EF-S 18-55mm", 
     "description": "\"<b>Take your pictures to the next level with EOS 750D</b>\\n- Effortlessly take your pictures to the next level with the latest DSLR technology and Scene Intelligent Auto mode.\\n- Effortlessly capture stunning detail in any situation\\n- Record cinematic movies as easily as you shoot stills\\n- Easily connect and share your images with the world\\n\\n<b>Take your pictures to the next level with EOS 750D</b>\\n<b>Range of shooting modes</b>\\nEffortlessly capture stunning images using the latest DSLR technology with Basic and Creative modes, which allow you to take as much or as little control as you like.\\n\\n<b>Moveable screen for creative framing</b>\\nExplore creative shooting angles and enjoy simple and intuitive access to controls using the 3.0\"\" (7.7cm) Vari Angle LCD touch screen\\n\\n<b>Intelligent Viewfinder</b>\\nEOS 750D features an Intelligent Viewfinder which gives a much enhanced shooting experience. As you look through the viewfinder you can more easily see the focus point and any active AF areas, also the shooting information is clearly displayed.\\n\\n<b>Effortlessly capture stunning detail in any situation</b>\\nCapture vivid, detailed, high-resolution images with better dynamic range, lower noise and excellent control over depth of field thanks to a 24.2 Megapixel APS-C sensor.\\n\\n<b>19 all cross-type AF points for accurate subject tracking</b>\\nKeep track of fast moving action thanks to a fast and accurate autofocus system comprising 19 cross-type AF points.\\n\\n<b>Fast processor for action</b>\\nA powerful DIGIC 6 processor delivers full resolution shooting at 5 fps � so you�ll never miss that decisive moment.\\n\\n<b>Great low light shots</b>\\nTake memorable low light pictures without using flash thanks to a large ISO sensitivity range of ISO 100-12800 (extendable to ISO 25600)\\n\\n<b>Record cinematic Full HD movies as easily as you shoot stills</b>\\nShoot superbly detailed Full HD movies with a cinematic feel thanks to DSLR control over depth of field. Record your movies in MP4 format for quicker online sharing and easier transfer to other devices.\\n\\n<b>Smoother results</b>\\nEasily shoot cinematic Full HD movies with Hybrid CMOS AF III to track movement and focus smoothly between subjects.\\n\\n<b>Empower your creativity with easy shooting modes</b>\\nLet the camera do the work for you and capture creative photos with ease using a range of Scene Modes\\n\\n<b>Creative movie modes</b>\\nExpand the range of shooting possibilities in movies with features like Miniature Effect in movie.\"", 
     "shortDescription": "\"22.3 x 14.9mm CMOS, 24.2 megapixels, 3:2, DIGIC 6, LCD, ISO 12800, Full HD Movie, USB, HDMI mini, SD/SDHC/SDXC, Black\"", 
     "summary": "\"Canon 750D + EF-S 18-55mm, EOS. Megapixel: 24.2 MP, Camera type: SLR Camera Kit, Sensor type: CMOS. Focal length range (f-f): 18 - 55 mm, Minimum focal length (35mm film equiv): 2.9 cm, Maximum focal length (35mm film equiv): 8.8 cm. Focus: TTL-CT-SIR, Closest focusing distance: 0.25 m. ISO sensitivity: 100, 6400, 12800, Auto, Light exposure modes: Auto, Manual, Light exposure control: Program AE. Fastest camera shutter speed: 1/4000 s, Slowest camera shutter speed: 30 s, Camera shutter type: Electronic\"", 
     "shortSummary": "\"Canon EOS 750D + EF-S 18-55mm, ATW, Cloudy, Custom modes, Daylight, Flash, Fluorescent L, Shade, Tungsten, Food, Landscape, Sports, Movie, Single image, Slide show, Battery, SLR Camera Kit, TTL-CT-SIR\"" 
    }, 
    "category": null, 
    "preview": { 
     "id": 1, 
     "highRes": "http://images.icecat.biz/img/norm/high/26171112-1991.jpg", 
     "lowRes": "http://images.icecat.biz/img/norm/low/26171112-1991.jpg", 
     "manual": "" 
    } 
} 

Diese für 1 Eigenschaft funktioniert. Weiß jemand, wie kann ich effizient rehash dieses um mit mehreren Eigenschaften zu arbeiten?


Ich habe versucht, dies zu tun:

// Create a service 
var service = { 

    // Sorts our products 
    sort: function (products, notations) { 

     // Call sort 
     products.sort(function (a, b) { 

      // For each notation 
      for (var i = 0; i < notations.length; i++) { 

       // Get our notation 
       var notation = notations[i]; 

       // Get our values 
       var aValue = _getPropertyValue(a, notation), 
        bValue = _getPropertyValue(b, notation); 

       console.log(bValue); 

       // If our attribute name is not the same as the second attribute 
       if (aValue <= bValue) { 

        // Return -1 
        return -1; 
       } 

       // Otherwise return 1 
       return 1; 
      } 
     }); 
    } 
}; 

und aufgerufen es wie folgt aus:

handler.sort(self.products, ['attributes.dimensions.weightIncludingBattery', 'attributes.network.wiFi']); 

aber dies scheint nur durch die erste Eigenschaft zu sortieren und nicht die zweite.

durch eine Iteration des Werts einer Eigenschaft Für den Zugriff:

+0

fügen Sie bitte ein Beispiel der Daten hinzu, die Sie sortieren mögen. –

+0

Könnten Sie bitte die Objektstruktur zeigen? – Redu

+1

Ok, ich habe einen Artikel aus dem Produkt-Array – r3plica

Antwort

1

Mit dem Link enthält, dass @Nina Scholz posted ich eine Reihe von Funktionen erstellen verwaltet, die schnell zu funktionieren scheint. Die Reihe der Funktionen sieht so aus:

// Private function to get the value of the property 
var _getPropertyValue = function (object, notation) { 

    // Get all the properties 
    var properties = notation.split('.'); 

    // If we only have one property 
    if (properties.length === 1) { 

     // Return our value 
     return object[properties]; 
    } 

    // Loop through our properties 
    for (var property in object) { 

     // Make sure we are a property 
     if (object.hasOwnProperty(property)) { 

      // If we our property name is the same as our first property 
      if (property === properties[0]) { 

       // Remove the first item from our properties 
       properties.splice(0, 1); 

       // Create our new dot notation 
       var dotNotation = properties.join('.'); 

       // Find the value of the new dot notation 
       return _getPropertyValue(object[property], dotNotation); 
      } 
     } 
    } 
}; 

// Get our fields 
var _getFields = function (notations) { 

    // Create our array 
    var fields = []; 

    // For each notation 
    angular.forEach(notations, function (notation) { 

     // Get our field 
     var names = notation.split('.'), 
      len = names.length, 
      name = names[len - 1]; 

     // Push our name into our array 
     fields.push({ name: name, notation: notation }); 
    }); 

    // Return our fields 
    return fields; 
}; 

// Create a mapped array 
var _createMapped = function (array, notations) { 

    // Get our fields 
    var fields = _getFields(notations); 

    // Create our mapped array 
    var mapped = array.map(function (a, i) { 

     // Create our object 
     var obj = { 
      index: i 
     }; 

     // For each of our fields 
     angular.forEach(fields, function (field) { 

      // Map our field 
      obj[field.name] = _getPropertyValue(a, field.notation); 
     }); 

     // Return our object 
     return obj; 
    }); 

    // Return our mapped array 
    return mapped; 
}; 

// Create a service 
var service = { 

    // Sorts our products 
    sort: function (products, notations) { 

     // Get our fields 
     var mapped = _createMapped(products, notations); 

     // Sort our mapped array 
     mapped.sort(function (a, b) { 

      // Loop through our properties 
      for (var i = 0; i < notations.length; i++) { 

       // Get our value (skip the first) 
       var o1 = a[i + 1]; 
       var o2 = b[i + 1]; 

       // Compare the values 
       if (o1 < o2) return -1; 
       if (o1 > o2) return 1; 
      } 

      // Default return 
      return 0; 
     }); 

     // Get our result 
     var result = mapped.map(function (item) { 
      return products[item.index]; 
     }); 

     // Return our result 
     return result; 
    } 
}; 

// Return our service 
return service; 
0

mehrere Eigenschaften Sortierung über können wie im folgenden Beispiel

var data = [ 
 
\t   { 
 
\t   a : 10, 
 
\t   b : 24 
 
      }, 
 
\t   { 
 
\t   a : 11, 
 
\t   b : 20 
 
      }, 
 
\t   { 
 
\t   a : 12, 
 
\t   b : 21 
 
      }, 
 
\t   { 
 
\t   a : 12, 
 
\t   b : 10 
 
      }, 
 
\t   { 
 
\t   a : 10, 
 
\t   b : 12 
 
      }, 
 
\t   { 
 
\t   a : 15, 
 
\t   b : 7 
 
      }, 
 
\t   { 
 
\t   a : 10, 
 
\t   b : 18 
 
      } 
 
      ] 
 
var sortData = (arr, prop1, prop2) => arr.sort((p,c) => p[prop1] < c[prop1] ? -1: p[prop1] == c[prop1] ? p[prop2] <= c[prop2] ? -1 : 1: 1); 
 
     sorted = sortData(data,"a","b"); 
 

 
document.write("<pre>" + JSON.stringify(sorted,null,2) + "</pre>");

+0

Ich habe ein Update zu meiner Frage hinzugefügt, da ich nicht glaube, dass Ihre Lösung das ist, was ich brauche. – r3plica

+0

@ r3plica Ich habe einige Korrekturen vorgenommen. Sehen Sie, ob es eine Idee gibt. – Redu

0

Grundsätzlich Sie brauchen etwas, wie das getan werden das Objekt

function getValue(string, object) { 
    return string.split('.').reduce(function (r, a) { 
     return r[a]; 
    }, object); 
} 

Und für den Sortiermechanismus die Iteration über die gewünschten Sortierparameter. Eigentlich nehme ich an, dass alle Werte Strings sind.

Der Nachteil davon ist eine sehr langsame Sortierung, wegen des Lookup-Mechanismus eines bestimmten Wertes.

Ein schneller Weg sorting with map wäre, wo die Karte nur die gewünschten Werte aus dem getValue

+0

Ihre ** getValue ** -Funktion, ist das das gleiche wie mein ** _ getPropertyValue **? – r3plica

+0

ja, ich würde sagen, es liefert das gleiche. –

+1

Ich mag diese Funktion ** getValue **, ich wusste nicht einmal, dass Sie das tun können. – r3plica

Verwandte Themen