JS使用lodash根据对象值对上级对象数组进行排序

时间:2018-05-24 06:20:52

标签: javascript arrays sorting object

我有以下结构:

let drives = [
    {id: 1, moves:[
        {moveId: 1, difference: 1},
        {moveId: 2, difference: 2}]
    },
    {id: 2, moves:[
        {moveId: 1, difference: -2}]
    },
    {id: 3, moves:[
        {moveId: 1, difference: 5}, 
        {moveId: 2, difference: 2}, 
        {moveId: 3, difference: 4}]
    },
    {id: 4, moves:[
        {moveId: 1, difference: 6}]
    }
]

现在我想根据移动的差异对驱动器数组进行排序。结果应该是这样的(取决于排序顺序)。

let drives = [
    {id: 2, moves:[
        {moveId: 1, difference: -2}]
    },
    {id: 1, moves:[
        {moveId: 1, difference: 1},
        {moveId: 2, difference: 2}]
    },
    {id: 3, moves:[
        {moveId: 2, difference: 2},
        {moveId: 3, difference: 4},
        {moveId: 1, difference: 5}]
    },
    {id: 4, moves:[
        {moveId: 1, difference: 6}]
    }
]

我尝试使用此代码

使用lodash执行此操作
_.orderBy(drives, 'moves.difference', 'asc');

但这似乎什么都不做。 有谁知道如何处理这个?

4 个答案:

答案 0 :(得分:0)

您的问题似乎必须解决两个部分。首先对它们自己的数组进行排序,所以答案如下所示



let drives = [
      {id: 1, moves:[
               {moveId: 1, difference: 1},
               {moveId: 2, difference: 2}]
      },
      {id: 2, moves:[
               {moveId: 1, difference: -2}]
      },
      {id: 3, moves:[
               {moveId: 1, difference: 5}, 
               {moveId: 2, difference: 2}, 
               {moveId: 3, difference: 4}]
      }
    ]

    drives.forEach(x=> {
	    x.moves.sort(function (a, b) {
        return a.difference - b.difference;
      });
    });

    drives.sort(function (a, b) {
      return a.moves[0].difference - b.moves[0].difference;
    });
    
    console.log(drives);




关于第二部分,我不确定你在id 2和id 1之间交换的条件是什么。

let drives = [
  {id: 1, moves:[
       {moveId: 1, difference: 1},
       {moveId: 2, difference: 2}]
  },
  {id: 2, moves:[
       {moveId: 1, difference: -2},
       {moveId: 2, difference: 4}]
  }]

如果对于上述情况,id:2会先出现还是保持相同的序列?

答案 1 :(得分:0)

你可以排序两次。首先,对moves数组进行排序。对所有moves数组进行排序后。然后根据第一个索引处的difference值进行排序。

let drives = [ {id: 1, moves:[ {moveId: 1, difference: 1}, {moveId: 2, difference: 2}] }, {id: 2, moves:[ {moveId: 1, difference: -2}] }, {id: 3, moves:[ {moveId: 1, difference: 5}, {moveId: 2, difference: 2}, {moveId: 3, difference: 4}] }, {id: 4, moves:[{moveId: 1, difference: 6}] } ];
drives.forEach(o => o.moves.sort((a,b) => a.difference - b.difference));
drives.sort((a,b) => a.moves[0].difference - b.moves[0].difference);
console.log(drives);

答案 2 :(得分:0)

您可以使用嵌套方法对内部moves进行排序,然后通过将第一个元素排序来进行外部移动。

var drives = drives = [{ id: 1, moves: [{ moveId: 1, difference: 1 }, { moveId: 2, difference: 2 }] }, { id: 2, moves: [{ moveId: 1, difference: -2 }] }, { id: 3, moves: [{ moveId: 1, difference: 5 }, { moveId: 2, difference: 2 }, { moveId: 3, difference: 4 }] }, { id: 4, moves: [{ moveId: 1, difference: 6 }] }];

console.log(
    _(drives)
         .map(o => Object.assign({}, o, { moves: _.sortBy(o.moves, 'difference') }))
         .sortBy(({ moves: [{ difference }] }) => difference)
         .value()
);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

答案 3 :(得分:0)

您的情况与我看到的方式有两种解决方案。 为了获得所需的解决方案,您需要确定要对驱动器进行排名的方法。不幸的是,您的方法可能在将来导致意外结果。

你会发现移动中会有重复的差异值,在这种情况下你需要决定哪个驱动器在排序算法中会有更多的权重。

下面你可以找到一个rankMap对象,它建立了各个驱动器之间最大和最小的差异,以便以后帮助你对数组进行排序。

希望这有帮助

    let drives = [
    {id: 1, moves:[
        {moveId: 1, difference: 1},
        {moveId: 2, difference: 2}]
    },
    {id: 2, moves:[
        {moveId: 1, difference: -2}]
    },
    {id: 3, moves:[
        {moveId: 1, difference: 5}, 
        {moveId: 2, difference: 2}, 
        {moveId: 3, difference: 4}]
    }
];

// we build a rankMap by which we will later sort the array of objects
let rankMap = {};

drives = drives.map(drive => {
    let
        biggestDiff = null,
        smallestDiff = null;

    let moves = _.orderBy(drive.moves, move => {
        if(biggestDiff < move.difference || biggestDiff === null) {
            biggestDiff = move.difference;
        }
        if(smallestDiff > move.difference || smallestDiff === null) {
            smallestDiff = move.difference;
        }

        return move.difference;
    }, ['asc']);

    rankMap[drive.id] = {
        smallestDiff: smallestDiff,
        biggestDiff: biggestDiff
    };

    return Object.assign({}, drive, {
        moves: moves
    });
});

let
    sortedByBiggestDifference = _.orderBy(drives, drive => rankMap[drive.id].biggestDiff, ['asc']),
    sortedBySmallestDifference = _.orderBy(drives, drive => rankMap[drive.id].smallestDiff, ['asc']);

console.log(drives);
console.log(sortedByBiggestDifference);
console.log(sortedBySmallestDifference);