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

时间:2018-08-09 17:14:55

标签: javascript arrays algorithm object

我很想知道如何实现我所需要的。我最初的对象数组是70k个对象,每个对象具有15个属性。通过过滤和映射,我将数据集简化为我认为是相关的部分。我需要基于每个对象的4个属性中的每个属性返回一个新的对象数组,它们分别是重复的id's和每个levels的不同的code。我过滤的数据看起来像这样。

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"}]

我需要为每个id的{​​{1}}中的current中的每个Y实现一个目标,我需要为此找到最大值code level。因此,对于上面的示例,结果输出将是一个对象数组,如下所示:

code

我什至不确定我想要的东西是否可行,或者我是否在以错误的方式考虑。我整个上午都在绞尽脑汁想找出解决办法。

4 个答案:

答案 0 :(得分: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);

答案 1 :(得分: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 :(得分:2)

您可以简化为地图并获取其值

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

答案 3 :(得分: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,然后必须将对象中的所有值转换为数组