简体   繁体   English

按键值在Javascript中对对象数组进行排序

[英]Sort an array of objects in Javascript by key value

First time poster, long time reader. 第一次海报,长时间阅读。 I'm having a problem sorting an array of objects, this is homework so I'm not asking for someone to write the code for me just point me in the right direction or show me my over sight. 我在排序一系列对象时遇到问题,这是家庭作业,所以我不是要求别人为我编写代码,只是指向正确的方向或向我展示我的视线。 The object is to write a function to sort an array of objects when passing in an array and a key ie: 对象是在传入数组和键时写一个函数来对对象数组进行排序,即:

([{a:2},{b:2},{a:1},{a:3},{b:3},{b:1}], “a”)

Should return 应该回来

[{a:1},{a:2},{a:3},{b:1},{b:2},{b:3}];

I can't use anything like underscore.js or node.js 我不能使用像underscore.js或node.js这样的东西

    //example array to use
    var testarr = [{a:2},{b:2},{a:1},{a:3},{b:3},{b:1}];
    console.log("array sort test: should look like [{a:1},{a:2},{a:3},{b:1},{b:2},{b:3}]");

    //first attempt 
    var sortArrayByKey = function (arr1, key) {
            (arr1.sort(function(a,b){
            return a[key] - b[key];}));
            return arr1;
    };
    //still only returns testarr
    console.log(sortArrayByKey(testarr, "a") );

    //second attempt
    var sortArrayByKey1 = function (array, key) {
    var compareByKey = function (a, b) {
            var x = a[key]; var y = b[key];
            return x - y;
    }
    array.sort(compareByKey);        
    return array;
    };
    //still only returns testarr
    console.log(sortArrayByKey1(testarr, “a”));

![pic of requirements in-case i'm describing it wrong photo ![我在描述错误照片的情况下的要求图片

Hmm.. this is a weird one. 嗯..这是一个奇怪的。 First you need to check if one of the keys is the priority key and sort based on that. 首先,您需要检查其中一个密钥是否为优先级密钥,并根据该密钥进行排序。 Then if both keys are equal sort by the values. 然后,如果两个键相等,则按值排序。 The problem is that there is no straightforward way to get the key but you can use the for .. in loop. 问题是没有直接的方法来获取密钥,但你可以使用for .. in循环。

I'm going to assume that each object contains only one property otherwise the code will not make sense since property is unordered in objects: 我将假设每个对象只包含一个属性,否则代码将没有意义,因为属性在对象中是无序的:

function sortPreferredKey(arr,key) {
    arr.sort(function(a,b){
        // get the keys of each object
        for (var a_key in a) {break}
        for (var b_key in b) {break}
        if (a_key != b_key) {
            if (a_key == key) return 1;
            else if (b_key == key) return -1;
            else return 0;
        }
        return a[a_key] - b[b_key];
    });
}

I may have gotten the order of sort wrong but you get the idea. 我可能已经得到了错误的顺序,但你明白了。 It's really weird that you'd even need to do something like this. 你甚至需要做这样的事情真的很奇怪。

Here's my solution. 这是我的解决方案。 I made it so you can also add more keys and sort them too. 我做了它,所以你也可以添加更多的密钥并对它们进行排序。

Fiddle - http://jsfiddle.net/Q7Q9C/3/ 小提琴 - http://jsfiddle.net/Q7Q9C/3/

function specialSort(arrayToSort, keyOrder) {
    arrayToSort = arrayToSort.sort(function (a, b) {
        for (var key in keyOrder) {
            if (!keyOrder.hasOwnProperty(key)) {
                continue;
            }
            var aKey = keyOrder[key];
            if (typeof a[aKey] === "undefined" && typeof b[aKey] === "undefined") {
                continue;
            }
            if (typeof a[aKey] !== "undefined" && typeof b[aKey] === "undefined") {
                return -1;
            }
            if (typeof a[aKey] === "undefined" && typeof b[aKey] !== "undefined") {
                return 1;
            }
            if (a[aKey] > b[aKey]) {
                return 1;
            }
            else if (a[aKey] < b[aKey]) {
                return -1;
            }
        }
        return 0;
    });
    return arrayToSort;
}
var arrayToSort = [
    {a:2},
    {b:2},
    {a:1},
    {a:3},
    {b:3},
    {c:3},
    {c:2},
    {b:1}
];
var keyOrder = ["a", "b", "c"];
var sortedArray = specialSort(arrayToSort, keyOrder);
console.log(JSON.stringify(sortedArray));

This is the best I can come up with. 这是我能想到的最好的。 It will sort all the elements with the given key to the front; 它将使用给定键对所有元素进行排序; the elements without the key will be in the back, but they'll be in an unpredictable order. 没有钥匙的元素将在后面,但它们将处于不可预测的顺序。

function sortArrayByKey(arr, key) {
    function compareKey(a, b) {
        if (a.hasOwnProperty(key)) {
            if (b.hasOwnProperty(key)) {
                return a[key] - b[key];
            } else {
                return -1;
            }
        } else if (b.hasOwnProperty(key)) {
            return 1;
        } else {
            return 0;
        }
    }
    arr.sort(compareKey);
    return arr;
}

Here's a solution that makes a guess what to do if neither object being compared in the array has the passed in comparison key: 这是一个解决方案,如果数组中的比较对象都没有传入比较键,则可以猜测该怎么做:

var data = [{a:2},{b:2},{a:1},{a:3},{b:3},{b:1}];

function sortByProperty(array, propName) {

    function findFirstProperty(obj) {
        for (x in obj) {
            if (obj.hasOwnProperty(x)) {
                return x;
            }
        }
    }

    return array.sort(function(first, second) {
        var firstHasProp = propName in first;
        var secondHasProp = propName in second;
        if (firstHasProp) {
            if (secondHasProp) {
                // both have the property
                return first[propName] - second[propName];
            } else {
                // only first has the property
                return -1;
            }
        } else if (secondHasProp){
            // only second has the property
            return 1;
        } else {
            // Neither sort candidate has the passed in property name
            // It is not clear what you want to do here as no other property
            //    name has been specified
            return first[findFirstProperty(first)] - second[findFirstProperty(second)]
        }
    });
}

Working demo: http://jsfiddle.net/jfriend00/PFurT/ 工作演示: http//jsfiddle.net/jfriend00/PFurT/

Logically, here's what it does: 从逻辑上讲,这是它的作用:

  1. If both comparison candidates have the desired property, then simply sort by the value of that property. 如果两个比较候选者都具有所需属性,则只需按该属性的值进行排序。
  2. If only one comparison candidate has the desired property, then make the one with the desired property be first in the sort order 如果只有一个比较候选者具有所需属性,则使具有所需属性的属性成为排序顺序中的第一个
  3. If neither comparison candidate has the desired property, find the first other property on the object and sort by that. 如果两个比较候选者都没有所需的属性,请在对象上找到第一个其他属性并按其排序。 This is a guess because you don't really explain what you want to happen in this case, but it works for the data example you provided. 这是一个猜测因为你没有真正解释在这种情况下你想要发生什么,但它适用于你提供的数据示例。

Here's a version that works like the above one, but is has been extended to sort properties that are not the passed in property in alpha order and to deal with empty objects (with no properties) so they go at the end of the sort: 这是一个与上面的版本类似的版本,但是已经扩展为对按字母顺序不是传入属性的属性进行排序,并处理空对象(没有属性),因此它们在排序结束时进行:

var data = [{c:4},{a:2},{b:2},{a:1},{a:3},{b:3},{b:1},{},{c:3}];

function sortByProperty(array, propName) {
    function findFirstProperty(obj) {
        for (x in obj) {
            if (obj.hasOwnProperty(x)) {
                return x;
            }
        }
    }
    return array.sort(function(first, second) {
        var firstHasProp = propName in first;
        var secondHasProp = propName in second;
        if (firstHasProp) {
            if (secondHasProp) {
                // both have the property
                return first[propName] - second[propName];
            } else {
                // only first has the property
                return -1;
            }
        } else if (secondHasProp){
            // only second has the property
            return 1;
        } else {
            // Neither sort candidate has the passed in property name
            // It is not clear what you want to do here as no other property
            //    name has been specified
            var firstProp = findFirstProperty(first);
            var secondProp = findFirstProperty(second);
            if (firstProp === undefined && secondProp === undefined) {
                return 0;
            } else if (firstProp === undefined) {
                return 1;
            } else if (secondProp === undefined) {
                return -1;
            }
            else if (firstProp === secondProp) {
                return first[firstProp] - second[secondProp];
            } else {
                return firstProp.localeCompare(secondProp);
            }
        }
    });
}

Working demo: http://jsfiddle.net/jfriend00/6QsVv/ 工作演示: http//jsfiddle.net/jfriend00/6QsVv/

The documentation for the sort method is here . sort方法的文档在这里 The compare function: 比较功能:

should be a function that accepts two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y. 应该是一个接受两个参数x和y的函数,如果x <y则返回负值,如果x = y则返回零,如果x> y则返回正值。

The function is passed the values in the array, so it's like calling the function with: 该函数传递给数组中的 ,因此就像调用函数一样:

compareFunction({a:2},{b:2});

What you seem to want to do is sort on the property name first, then on the value. 你似乎想要做的是首先对属性名称进行排序,然后对值进行排序。 The problem with that is that you can't guarantee what order the property names are returned in. In this case, if you have exactly one own property for each object, you can do: 问题是您无法保证返回属性名称的顺序。在这种情况下,如果每个对象只有一个属性,则可以执行以下操作:

// Return first own property returned by in
// ORDER IS NOT GUARANTEED
function getPropName(o) {
  for (var p in o) {
    if (o.hasOwnProperty(p)) {
      return p;
    }
  }
}

function specialSort(array, key) {
  array.sort(function (a, b) {
    var aProp = getPropName(a);
    var bProp = getPropName(b);
    // If properties are the same, compare value
    if (aProp == bProp) {
      return a[aProp] - b[bProp];
    }

    // Otherwise, compare keys
    return aProp == key? -1 : bProp == key? 1 : aProp.charCodeAt(0) - bProp.charCodeAt(0);
  });
  return array;
}

The above will also sort any other keys (c, d, e, etc.) after the preferred key so: 以上还将对首选键后的任何其他键(c,d,e等)进行排序,以便:

var a = [{c:3},{a:2},{b:2},{c:2},{a:1},{a:3},{b:3},{b:1},{c:1}]

specialSort(a, 'b'); // [{b:1}, {b:2}, {b:3}, {a:1}, {a:2}, {a:3}, {c:1}, {c:2}, {c:3}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM