根据现有对象数组的多个属性返回新的对象数组。

4

我正在努力思考如何达成我所需的目标。我的初始对象数组有70k个对象,每个对象都有15个属性。通过过滤和映射,我已经将数据集缩小到我认为是相关部分。我需要根据每个对象的4个属性返回一个新的对象数组,其中每个id都是重复的,并且每个codelevel是不同的。我的筛选数据如下所示。

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, 
             {id: "12345", level: "0", current: "N", code: "1"},
             {id: "54321", level: "1", current: "N", code: "201"},
             {id: "54321", level: "2", current: "Y", code: "201"}, 
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "Y", code: "401"},
             {id: "54321", level: "1", current: "N", code: "401"},
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "N", code: "301"},
             {id: "121212", level: "0", current: "N", code: "3"},
             {id: "121212", level: "1", current: "N", code: "3"}]

我需要实现的是对于任何Y的任何current的每个id,我需要查找该code的最大level。因此,对于上面的示例,结果输出将是以下对象数组:

const result = [{id: "12345", max: "1", code: "1"}, 
                {id: "54321", max: "3", code: "201"},
                {id: "54321", max: "1", code: "401"}]

我甚至不确定我想要的是否可能,或者我是否在错误的方向上思考。我整个早上一直在绞尽脑汁地寻找解决方案。


如果“对于任何Y电流”那么最大值不应该是1、0、2而不是1、3、1吗? - mickl
@mickl,我可能表述不太准确,但是对于每个id都有一个'Y'的任何code,我需要找到该id的最大值。我需要找到每个具有'Y'的代码的最大level - kemotoe
谢谢,我修改了我的答案,现在它返回你所需的内容。 - mickl
4个回答

2
你可以使用.filter().map()基于Y获取初始值,然后使用.reduce()获取最大值:

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, 
             {id: "12345", level: "0", current: "N", code: "1"},
             {id: "54321", level: "1", current: "N", code: "201"},
             {id: "54321", level: "2", current: "Y", code: "201"}, 
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "Y", code: "401"},
             {id: "54321", level: "1", current: "N", code: "401"},
             {id: "54321", level: "3", current: "N", code: "201"},
             {id: "54321", level: "0", current: "N", code: "301"},
             {id: "121212", level: "0", current: "N", code: "3"},
             {id: "121212", level: "1", current: "N", code: "3"}]

let initialValues = arr.filter(x => x.current === "Y")
         .map(x => ({ id: x.id, max: x.level, code: x.code }));

let result = arr.reduce((result,current) => {
 var value = result.find(x => x.id === current.id && x.code === current.code);
 if(!value) return result;
 if(value.max < current.level) {
  value.max = current.level;
 }
 return result;
}, initialValues);

console.log(result);


非常好用。谢谢! - kemotoe

2

您可以简单地使用 Array.reduce()Object destructuring 来实现。构建一个映射,其中每个键都是 idcode 的组合。只需在映射上使用 Object.values() 即可获得所需结果:

const arr = [{id: "12345", level: "1", current: "Y", code: "1"}, {id: "12345", level: "0", current: "N", code: "1"}, {id: "54321", level: "1", current: "N", code: "201"}, {id: "54321", level: "2", current: "Y", code: "201"}, {id: "54321", level: "3", current: "N", code: "201"}, {id: "54321", level: "0", current: "Y", code: "401"}, {id: "54321", level: "1", current: "N", code: "401"}, {id: "54321", level: "3", current: "N", code: "201"}, {id: "54321", level: "0", current: "N", code: "301"}, {id: "121212", level: "0", current: "N", code: "3"}, {id: "121212", level: "1", current: "N", code: "3"}];
             
const result = Object.values(arr.reduce((a,{level,current, ...props})=>{
    a[props.id+"_"+props.code] = a[props.id+"_"+props.code] || props;
    a[props.id+"_"+props.code].max = Math.max((a[props.id+"_"+props.code].max || 0), level);
  return a;
},{}));
console.log(result);


2
你可以将其转换为Map并获取它的值。

const arr = [{id: "12345", level: "1", current: "Y", code: "1"},
    {id: "12345", level: "0", current: "N", code: "1"},
    {id: "54321", level: "1", current: "N", code: "201"},
    {id: "54321", level: "2", current: "Y", code: "201"},
    {id: "54321", level: "3", current: "N", code: "201"},
    {id: "54321", level: "0", current: "Y", code: "401"},
    {id: "54321", level: "1", current: "N", code: "401"},
    {id: "54321", level: "3", current: "N", code: "201"},
    {id: "54321", level: "0", current: "N", code: "301"},
    {id: "121212", level: "0", current: "N", code: "3"},
    {id: "121212", level: "1", current: "N", code: "3"}];
    
    
const res = arr.reduce((a, b) =>
  b.current === 'Y' ?
  a.set(b.id + b.code, (a.get(b.id + b.code) || {
    level: Number.MIN_SAFE_INTEGER
  }).level < b.level ? b : a.get(b.id + b.code)) :
  a, new Map);
console.log([...res.values()]);


OP期望不同的结果。 - mickl

0
const resultObject = (arr, filter) => arr.reduce((sum, element) => {
  const currentInSum = sum[element.id];
  const filterSatisfied = element.current === filter;
  const isHighestLevel = !currentInSum  || currentInSum.level < element.level;
  if(filterSatisfied && isHighestLevel){
     sum[element.id] = element;
  }
  return sum;
}, {});
const result = Object.values(resultObject(arr, "Y"));

基本上您想要使用一个对象来检查元素是否已经添加,如果当前级别高于已添加的级别,则替换它,如果这是第一次出现,则只需将其添加到对象中。

最后,只需从对象中获取所有值以将其转换为数组,您不需要关心键,即对象的 ID。

该算法需要 O(n*2) 的执行时间,因为您必须先遍历 arr,然后您必须将对象中的所有值转换为数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接