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

时间:2013-10-24 01:56:36

标签: javascript arrays sorting

第一次海报,长时间读者。我在排序一系列对象时遇到问题,这是家庭作业,所以我不是要求别人为我编写代码,只是指向正确的方向或向我展示我的视线。目标是在传入数组和键时编写一个函数来对对象数组进行排序,即:

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

应该返回

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

我不能使用像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”));

![我在描述错误时需求的图片photo

5 个答案:

答案 0 :(得分:1)

嗯..这是一个奇怪的。首先,您需要检查其中一个密钥是否为优先级密钥,并根据该密钥进行排序。然后,如果两个键相等,则按值排序。问题是获取密钥没有直接的方法,但您可以使用for .. in循环。

我将假设每个对象只包含一个属性,否则代码将没有意义,因为属性在对象中是无序的:

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

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

答案 1 :(得分:1)

这是我的解决方案。我做了它,所以你也可以添加更多的键并对它们进行排序。

小提琴 - 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 :(得分:0)

这是我能想到的最好的。它将使用给定键对所有元素进行排序;没有钥匙的元素将在后面,但它们将处于不可预测的顺序。

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

答案 3 :(得分:0)

这是一个解决方案,如果数组中的比较对象都没有传入比较键,那么可以猜测该怎么做:

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

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

从逻辑上讲,这就是它的作用:

  1. 如果两个比较候选者都具有所需属性,则只需按该属性的值排序。
  2. 如果只有一个比较候选者具有所需属性,则在排序顺序中将具有所需属性的属性设为第一个
  3. 如果两个比较候选者都没有所需的属性,请在对象上找到第一个其他属性并按其排序。这是一个猜测,因为你没有真正解释在这种情况下你想要发生什么,但它适用于你提供的数据示例。

  4. 这是一个与上面这个版本类似的版本,但是它已被扩展为对按字母顺序不是传入属性的属性进行排序,并处理空对象(没有属性),因此它们位于结束时分类:

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

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

答案 4 :(得分:0)

sort 方法的文档是here。比较功能:

  

应该是一个接受两个参数x和y并返回一个的函数   如果x <负值则为负值y,如果x = y则为零,或者如果x> y则为正值;收率

该函数在数组中传递,因此就像调用函数一样:

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

您似乎想要做的是首先对属性名称进行排序,然后对值进行排序。问题在于您无法保证返回属性名称的顺序。在这种情况下,如果每个对象都有完全一个自己的属性,则可以执行以下操作:

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

以上内容还将对首选键后的任何其他键(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}]