我试图通过多个属性对数组进行排序,但问题是我的数组是多维的。 目前我已经建立了这个:
// 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;
这是阵列(产品)中的一个项目
{
"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": ""
}
}
这适用于1个属性。有谁知道如何有效重新使用多个属性?
我试过这样做:
// 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;
}
});
}
};
并像这样调用它:
handler.sort(self.products, ['attributes.dimensions.weightIncludingBattery', 'attributes.network.wiFi']);
但这似乎只是按第一个属性而不是第二个属性排序。
答案 0 :(得分:1)
通过@Nina Scholz发布的链接,我设法创建了一组似乎快速运行的功能。这组函数如下所示:
// 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;
答案 1 :(得分:0)
可以按照以下示例
对多个属性进行排序
var data = [
{
a : 10,
b : 24
},
{
a : 11,
b : 20
},
{
a : 12,
b : 21
},
{
a : 12,
b : 10
},
{
a : 10,
b : 12
},
{
a : 15,
b : 7
},
{
a : 10,
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>");
&#13;
答案 2 :(得分:0)
基本上你需要这样的东西:
对于属性值的访问,通过对象
进行迭代function getValue(string, object) {
return string.split('.').reduce(function (r, a) {
return r[a];
}, object);
}
对于排序机制,迭代所需的排序参数。实际上我假设所有的值都是字符串。
// handler.sort
function sort(array, order) {
array.sort(function (a, b) {
var r = 0;
order.some(function (s) {
r = getValue(s, a).localeCompare(getValue(s, b));
return r;
});
return r;
});
}
这样做的缺点是排序非常慢,因为特定值的查找机制。
更快的方式是sorting with map,其中地图仅包含getValue