将重复的对象值转换为数组Javascript

4

我花了几个小时来寻找处理这个对象数组的方法:

[
  {
    "value": "foo01",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo02",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo03",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo04",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo03",
    "name": "bar2"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo01",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo04",
    "name": "bar2"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo04",
    "name": "bar3"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar3"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo02",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo04",
    "name": "bar4"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar4"
  }
]

我期望的JSON应该像这样:

[
  {
    "name":"bar",
    "value":[
      {
        "value": "foo01",
        "Diagnosis_Code": ["Tidak ada"],
        "name": "bar",
      },
      {
        "value": "foo02",
        "Diagnosis_Code": ["Tidak ada"],
        "name": "bar",
      },
      {
        "value": "foo03",
        "Diagnosis_Code": ["Tidak ada"],
        "name": "bar",
      },
      {
        "value": "foo04",
        "Diagnosis_Code": ["Tidak ada"],
        "name": "bar",
      }
    ]
  },
  {
    "name": "bar2",
    "value": [
      {
        "value": "val1",
        "Diagnosis_Code": ["foo03"],
        "name": "bar2",
      },
      {
        "value": "val2",
        "Diagnosis_Code": ["foo01"],
        "name": "bar2",
      },
      {
        "value": "val3",
        "Diagnosis_Code": ["foo02", "foo04"],
        "name": "bar2",
      }
    ]
  },
  {
    "name": "bar3",
    "value":[
      {
        "value": "val1",
        "Diagnosis_Code": ["foo01"],
        "name": "bar3",
      },
      {
        "value": "val2",
        "Diagnosis_Code": ["foo03", "foo04"],
        "name": "bar3",
      },
      {
        "value": "val3",
        "Diagnosis_Code": ["foo02"],
        "name": "bar3",
      },
    ]
  },
  {
    "name": "bar4",
    "value": [
      {
        "value": "val1",
        "Diagnosis_Code": ["foo01", "foo02", "foo04"],
        "name": "bar4",
      },
      {
        "value": "val2",
        "Diagnosis_Code": ["foo03"],
        "name": "bar4",
      },
    ]
  },
]

我希望能将重复的name值放入Object中,如果json的Diagnosis_Code与另一个值相同,则将其放入数组中。
目前我使用的代码只是使用reduce来处理name,但我不知道如何处理Diagnosis_Code属性。

var orgArray = [{"value":"foo01","Diagnosis_Code":"Tidak ada","name":"bar"},{"value":"foo02","Diagnosis_Code":"Tidak ada","name":"bar"},{"value":"foo03","Diagnosis_Code":"Tidak ada","name":"bar"},{"value":"foo04","Diagnosis_Code":"Tidak ada","name":"bar"},{"value":"val1","Diagnosis_Code":"foo03","name":"bar2"},{"value":"val2","Diagnosis_Code":"foo01","name":"bar2"},{"value":"val3","Diagnosis_Code":"foo02","name":"bar2"},{"value":"val3","Diagnosis_Code":"foo04","name":"bar2"},{"value":"val1","Diagnosis_Code":"foo01","name":"bar3"},{"value":"val2","Diagnosis_Code":"foo03","name":"bar3"},{"value":"val2","Diagnosis_Code":"foo04","name":"bar3"},{"value":"val3","Diagnosis_Code":"foo02","name":"bar3"},{"value":"val1","Diagnosis_Code":"foo01","name":"bar4"},{"value":"val1","Diagnosis_Code":"foo02","name":"bar4"},{"value":"val1","Diagnosis_Code":"foo04","name":"bar4"},{"value":"val2","Diagnosis_Code":"foo03","name":"bar4"}];

var newArray = orgArray.reduce(function(acc, curr) {
  var findIfNameExist = acc.findIndex(function(item) {
    return item.name === curr.name;
  })
  if (findIfNameExist === -1) {
    let obj = {
      'name': curr.name,
      "value": [curr]
    }
    acc.push(obj)
  } else {
    acc[findIfNameExist].value.push(curr)
  }
  return acc;

}, []);
console.log(newArray)

有没有一种处理将重复的Diagnosis_Code转换成数组的方法?

2个回答

2

这里是另一个例子!

首先,我使用reduce来减少您的对象,然后使用map重新映射以获得期望的格式 ;)

这可能不是最佳性能的方法,但我认为这是更易于维护和阅读的方式。

希望这很清楚并且会对您有所帮助 :D

const input = [
  {
    "value": "foo01",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo02",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo03",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo04",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo03",
    "name": "bar2"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo01",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo04",
    "name": "bar2"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo04",
    "name": "bar3"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar3"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo02",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo04",
    "name": "bar4"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar4"
  }
];

// Condensed/reduced object.
let output = input.reduce((accum, item) => {
  if(!accum[item.name]) {
    accum[item.name] = {};
  }
  if(!accum[item.name][item.value]) {
    accum[item.name][item.value] = [];
  }
  accum[item.name][item.value].push(item.Diagnosis_Code);
  accum[item.name][item.value].original = item;
  return accum;
}, {});

// Object remapped to fit your expected format.
output = Object.keys(output).map((itemName) => {
  return {
    'name': itemName,
    'value': Object.keys(output[itemName]).map((valueName) => {
    const patchedOriginalItem = output[itemName][valueName].original;
    patchedOriginalItem['Diagnosis_Code'] = output[itemName][valueName];
      return patchedOriginalItem;
    })
  };
});

console.log(output);


我无法这样做,因为value[index].value将会是动态的。 - Flix
很抱歉,我不太明白问题,您能再具体说明一下吗?我的意思是,哪些部分会是动态的呢?您有一个静态对象,想要将其转换为另一种格式。 - sjahan
你的返回值数组中是硬编码的 name, value 和 Diagnosis_Code 键,但如果我在数组中有超过 3 个对象,我该如何处理这些数组呢?所以我需要声明其他的键,对吗? - Flix
好的,我明白了,你想要完全相同的原始对象!我会进行编辑 :) - sjahan
这就是它:)我只是在修补Diagnosis_Code属性,以获取压缩的数组版本;) - sjahan

1
使用.reduce将数组转换为对象,就像您正在做的那样,但是然后您需要两次使用.find来查看匹配的name,然后再查看匹配的value对象是否存在。仅使用一次find(或.findIndex)不足够。

const input = [
  {
    "value": "foo01",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo02",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo03",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "foo04",
    "Diagnosis_Code": "Tidak ada",
    "name": "bar"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo03",
    "name": "bar2"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo01",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar2"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo04",
    "name": "bar2"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar3"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo04",
    "name": "bar3"
  },
  {
    "value": "val3",
    "Diagnosis_Code": "foo02",
    "name": "bar3"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo01",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo02",
    "name": "bar4"
  },
  {
    "value": "val1",
    "Diagnosis_Code": "foo04",
    "name": "bar4"
  },
  {
    "value": "val2",
    "Diagnosis_Code": "foo03",
    "name": "bar4"
  }
];

const output = input.reduce((accum, item) => {
  const { name } = item;
  let foundNameObj = accum.find(({ name: findName }) => findName === name);
  if (!foundNameObj) {
    foundNameObj = { name, value: [] };
    accum.push(foundNameObj);
  }
  const foundValObj = foundNameObj.value.find(({ value }) => value === item.value);
  if (!foundValObj) {
    // value hasn't appeared before, we can just push the item:
    foundNameObj.value.push({...item, Diagnosis_Code: [item.Diagnosis_Code] });
    return accum;
  }
  foundValObj.Diagnosis_Code.push(item.Diagnosis_Code);
  return accum;
}, [])
console.log(output);

不要混用 varlet/const - 如果你正在使用 ES6,应该始终使用 const,除非需要重新赋值,此时请使用 let。(var 被提升并具有函数作用域而不是块级作用域,这是不直观的,可能会导致意外错误)

但是如果 Diagnosis_Code 只有一个值,你如何将其处理为数组? - Flix
哦,我以为当只有一个项目时它们会保持为单独的字符串,因为我滚动到了底部。在什么情况下,当只有一个值时,它们会变成数组而不是字符串? - CertainPerformance
虽然 Diagnosis_Code 没有任何条件限制,但如果只有一个或多个值,则它应该是一个数组。 - Flix
请修复您的 My Expected JSON,因为它包含字符串。 - CertainPerformance
抱歉,我没有意识到它还没有完成编辑,但是你的代码应该可以工作,无论如何还是谢谢。 - Flix

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