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

时间:2022-12-27 16:01:15

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

![我在描述错误照片的情况下的要求]

5 个解决方案

#1


1  

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));

#2


1  

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.

我可能已经得到了错误的顺序,但你明白了。你甚至需要做这样的事情真的很奇怪。

#3


0  

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;
}

#4


0  

The documentation for the sort method is here. The compare function:

sort方法的文档在这里。比较功能:

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>

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}]

#5


0  

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. 如果两个比较候选者都具有所需属性,则只需按该属性的值进行排序。

  3. If only one comparison candidate has the desired property, then make the one with the desired property be first in the sort order
  4. 如果只有一个比较候选者具有所需属性,则使具有所需属性的属性成为排序顺序中的第一个

  5. 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.
  6. 如果两个比较候选者都没有所需的属性,请在对象上找到第一个其他属性并按其排序。这是一个猜测,因为您没有真正解释在这种情况下您想要发生什么,但它适用于您提供的数据示例。


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/

#1


1  

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));

#2


1  

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.

我可能已经得到了错误的顺序,但你明白了。你甚至需要做这样的事情真的很奇怪。

#3


0  

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;
}

#4


0  

The documentation for the sort method is here. The compare function:

sort方法的文档在这里。比较功能:

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>

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}]

#5


0  

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. 如果两个比较候选者都具有所需属性,则只需按该属性的值进行排序。

  3. If only one comparison candidate has the desired property, then make the one with the desired property be first in the sort order
  4. 如果只有一个比较候选者具有所需属性,则使具有所需属性的属性成为排序顺序中的第一个

  5. 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.
  6. 如果两个比较候选者都没有所需的属性,请在对象上找到第一个其他属性并按其排序。这是一个猜测,因为您没有真正解释在这种情况下您想要发生什么,但它适用于您提供的数据示例。


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/