【问题标题】:JS Sorting superior array of objects depending on object value using lodashJS使用lodash根据对象值对高级对象数组进行排序
【发布时间】:2018-11-03 06:20:56
【问题描述】:

我有以下结构:

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

但这似乎无济于事。 有谁知道如何处理这个问题?

【问题讨论】:

  • 嗯..您是指每个驱动程序的差异总和吗?
  • 不是移动差异的总和。首先,每个驱动器对象的移动数组应按它们的差异(或任何其他键)排序。之后,驱动器数组应按移动的差异进行排序。 - 我编辑了我的帖子,希望现在更清楚。
  • @michaelT:请看看我的第一部分解决方案。至于第二部分,我已经提出了一个案例,请帮忙回答以便继续

标签: javascript arrays sorting object


【解决方案1】:

您可以使用嵌套方法,对内部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>

【讨论】:

  • 刚刚试了,按我的意愿工作!太好了,谢谢!
【解决方案2】:

您可以排序两次。首先,对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);

【讨论】:

  • 您的第二次排序解决方案仅基于第一项?你能看看我提出的案例吗?你认为 OP 想要什么?
【解决方案3】:

您的问题似乎需要解决两个部分。对于第一部分,首先对自己的数组进行排序,所以答案如下

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 会先出现还是保持相同的顺序?

【讨论】:

  • id 1 首先出现,然后是 id 2,因为 id 1 的移动最小差为 -3,而 id 2 为 -2(如果我使用升序)。当有两个驱动对象具有相同的最小移动差异时,两个对象的顺序无关紧要。
  • 看看解决方案。这与@Hassan的答案基本相同,只是语法差异
  • 您的解决方案也可以正常工作。谢谢!但我有一个问题:如果我想使用一个函数来使用动态排序键对驱动器数组进行排序,比如函数 sortDirves(sortKey) - 因为我在移动对象中拥有的不仅仅是差异键。如何在您的代码中插入动态排序键?只使用 a.moves[0][sortKey] 而不是 a.moves[0].difference ?
【解决方案4】:

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

您会发现移动之间会有重复的差异值,在这种情况下,您需要确定哪些驱动器在排序算法中具有更大的权重。

您可以在下面找到一个正在构建的 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-25
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    相关资源
    最近更新 更多