如何基于另一个对象数组对一个对象数组进行排序

时间:2019-02-04 23:26:24

标签: javascript arrays sorting

我有一个动态大小调整的数组,该数组根据最后选择的位置0来更改其顺序。问题是我想保留数组的原始顺序。

为此,我创建了一个附加变量,该变量设置为数组的原始排序。尽管选择项目后数组的某些值可能会更改,但name属性永远不会更改。我想利用这一事实将新数组排序到原始位置。

let keepRateOrder = rates.sort((a, b) => {  
        return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
      });


const rates = [
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]


const prevRates = [
{name:'Mail', isChoosen:false, cost:23 ...},
{name:'UPS', isChoosen:true, cost:63 ...},
{name:'FedEx', isChoosen:false, cost:33 ...}
]

3 个答案:

答案 0 :(得分:2)

可以使用findIndex解决此问题。在以下示例中,排序将按照Mail数组将prevRates放在第一位:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
];

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
];

let keepRateOrder = rates.sort((a, b) => {
  return prevRates.findIndex(p => p.name === a.name) - prevRates.findIndex(p => p.name === b.name);
});

console.log(keepRateOrder);

如果您首先indexOf,则可以使用map完成相同的操作。这样可以使代码更简洁:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
];

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
].map(x => x.name);

let keepRateOrder = rates.sort((a, b) => {
  return prevRates.indexOf(a.name) - prevRates.indexOf(b.name);
});

console.log(keepRateOrder);

还有一个解决方案,仅使用通过reduceRight创建的原始索引的哈希值:

const rates = [
  {name:'UPS', isChoosen:true, cost:63},
  {name:'Mail', isChoosen:false, cost:23},
  {name:'FedEx', isChoosen:false, cost:33}
]

const prevRates = [
  {name: 'Mail'},
  {name: 'UPS'},
  {name: 'FedEx'},
].reduceRight((a, x, i) => (a[x.name] = i, a), {});

let keepRateOrder = rates.sort((a, b) => {
  return prevRates[a.name] - prevRates[b.name];
});

console.log(keepRateOrder);

由于您说过可以在原始数组中添加或删除项目,因此请注意,上述所有解决方案都将首先放置新项目(因为它们在prevRates数组中的索引将返回为{{1} }。如果希望新项目显示在末尾,则需要执行以下操作:

-1

答案 1 :(得分:0)

首先使用.mapprevRates转换为仅包含name属性的数组,然后可以基于该名称数组使用.sort

const prevRates = [
  {name:'Mail', isChoosen:false, cost:23 },
  {name:'UPS', isChoosen:true, cost:63 },
  {name:'FedEx', isChoosen:false, cost:33 }
];
const rates = [
  {name:'UPS', isChoosen:true, cost:63 },
  {name:'Mail', isChoosen:false, cost:23 },
  {name:'FedEx', isChoosen:false, cost:33 }
];

const prevRatesNames = prevRates.map(({ name }) => name);
rates.sort((a, b) => (
  prevRatesNames.indexOf(a.name) - prevRatesNames.indexOf(b.name)
));
console.log(rates);

请记住,.sort就地排序-如果可以的话

let keepRateOrder = rates.sort...

然后keepRateOrder将只是对rates数组的另一个引用。如果要复制,而不是变异原始的rates数组,则必须先浅复制rates

const keepRateOrder = rates.slice().sort...

答案 2 :(得分:0)

如何向每个项目添加新属性以跟踪原始索引originalIndex。当您想退回原始订单时,使用该纸张进行排序,避免多余的副本。假设这就是您想要做的!