在Javascript数组中排列重复的对象以产生一个值

时间:2019-03-06 19:45:04

标签: javascript data-structures ecmascript-6

我正在尝试排列当前对象,如下图所示

var myValues = [
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "FIREFOX",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "BUZZZZZZ",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "PANTER",
    firstname: "Panty",
    id: "panty@panter.com",
    arrangeid: "PANTER",
    region: "PAN",
    secondname: "mc panty",
    status: "Approved"
},
{
    client: "BAT",
    firstname: "Bruce",
    id: "bat@bat.com",
    arrangeid: "BLACKBAT",
    region: "BLK",
    secondname: "Wyne",
    status: "Approved"
}

]

所以我有这个对象,前两个ID是相同的,但是它们具有不同的ranged。我想能够加入他们的行列。对象看起来像这样的地方:

    var myValues = [
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: ["BUZZZZZZ", "FIREFOX"],
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "PANTER",
    firstname: "Panty",
    id: "panty@panter.com",
    arrangeid: ["PANTER"],
    region: "PAN",
    secondname: "mc panty",
    status: "Approved"
},
{
    client: "BAT",
    firstname: "Bruce",
    id: "bat@bat.com",
    arrangeid: ["BLACKBAT"],
    region: "BLK",
    secondname: "Wyne",
    status: "Approved"
}

]

我有一个jsfidle here,在这里我可以得到结果。能做得更好,更清洁吗?我正确处理了吗?

5 个答案:

答案 0 :(得分:1)

您可以像这样使用reduce Object.values() spread syntax

var myValues = [{client:"FIRE",firstname:"Test",id:"test@fire.com",arrangeid:"FIREFOX",region:"FOP",secondname:"Testy",status:"Approved"},{client:"FIRE",firstname:"Test",id:"test@fire.com",arrangeid:"BUZZZZZZ",region:"FOP",secondname:"Testy",status:"Approved"},{client:"PANTER",firstname:"Panty",id:"panty@panter.com",arrangeid:"PANTER",region:"PAN",secondname:"mc panty",status:"Approved"},{client:"BAT",firstname:"Bruce",id:"bat@bat.com",arrangeid:"BLACKBAT",region:"BLK",secondname:"Wyne",status:"Approved"}];

const merged = myValues.reduce((acc, a) => {
  acc[a.client] = acc[a.client] || { ...a, arrangeid: [] };
  acc[a.client].arrangeid.push(a.arrangeid);
  return acc;
},{})

const output = Object.values(merged);
console.log(output)

累加器是一个对象,每个唯一的client作为其键,因此更容易对其进行分组。

{
  "FIRE": {
    "client": "FIRE",
    "firstname": "Test",
    "id": "test@fire.com",
    "arrangeid": [ "FIREFOX", "BUZZZZZZ" ],
    "region": "FOP",
    "secondname": "Testy",
    "status": "Approved"
  },
  "PANTER": {
    "client": "PANTER",
    "id": "panty@panter.com",
    "arrangeid": [
      "PANTER"
    ],
   ...
  }
  ...
}

答案 1 :(得分:0)

您可以使用reduce()

var myValues = [
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "FIREFOX",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "BUZZZZZZ",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "PANTER",
    firstname: "Panty",
    id: "panty@panter.com",
    arrangeid: "PANTER",
    region: "PAN",
    secondname: "mc panty",
    status: "Approved"
},
{
    client: "BAT",
    firstname: "Bruce",
    id: "bat@bat.com",
    arrangeid: "BLACKBAT",
    region: "BLK",
    secondname: "Wyne",
    status: "Approved"
}

]



let res = JSON.parse(JSON.stringify(myValues)).reduce((ac,a) => {
  let ind = ac.findIndex(x => x.id === a.id);
  a.arrangeid = [a.arrangeid];
  ind === -1 ? ac.push(a) : ac[ind].arrangeid.push(...a.arrangeid);
  return ac;
},[])
console.log(res);

答案 2 :(得分:0)

您可以创建一个Map来通过对象的ID来键对象,然后填充arrangeid数组:

const myValues = [{client: "FIRE",firstname: "Test",id: "test@fire.com",arrangeid: "FIREFOX",region: "FOP",secondname: "Testy",status: "Approved"},{client: "FIRE",firstname: "Test",id: "test@fire.com",arrangeid: "BUZZZZZZ",region: "FOP",secondname: "Testy",status: "Approved"}, {client: "PANTER",firstname: "Panty",id: "panty@panter.com",arrangeid: "PANTER",region: "PAN",secondname: "mc panty",status: "Approved"},{client: "BAT",firstname: "Bruce",id: "bat@bat.com",arrangeid: "BLACKBAT",region: "BLK",secondname: "Wyne",status: "Approved"}];

const map = new Map(myValues.map(o => [o.id, {...o, arrangeid: []}]));
myValues.forEach(o => map.get(o.id).arrangeid.push(o.arrangeid));
const result = [...map.values()];

console.log(result);

答案 3 :(得分:0)

对于较大的数据集,可以使用Map对象的查找功能来收集每个id的所有项目,然后可以将结果转换为所需的任何格式。您可以运行此代码段以查看结果。

function collectByField(data, key, prop) {
    const collection = new Map();
    for (const obj of data) {
         let item = collection.get(obj[key]);
         if (item) {
             // add this item's property to the array
             item[prop].push(obj[prop]);
         } else {
             // put a copy of our object into the Map
             // convert prop to an array with one initial item in it
             let copy = Object.assign({}, obj);
             copy[prop] = [obj[prop]];
             collection.set(obj[key], copy);
         }
    }
    // now use the Set to create final array output
    return Array.from(collection.values());
}

let myValues = [
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "FIREFOX",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "FIRE",
    firstname: "Test",
    id: "test@fire.com",
    arrangeid: "BUZZZZZZ",
    region: "FOP",
    secondname: "Testy",
    status: "Approved"
},
{
    client: "PANTER",
    firstname: "Panty",
    id: "panty@panter.com",
    arrangeid: "PANTER",
    region: "PAN",
    secondname: "mc panty",
    status: "Approved"
},
{
    client: "BAT",
    firstname: "Bruce",
    id: "bat@bat.com",
    arrangeid: "BLACKBAT",
    region: "BLK",
    secondname: "Wyne",
    status: "Approved"
}
];

console.log(collectByField(myValues, "id", "arrangeid"));

答案 4 :(得分:0)

这是一种稍微通用的方法,它使您可以按字段的任意组合进行分组,然后将某些给定的字段合并为一个数组:

const pick = (fields, obj) => fields.reduce((o, fld) => ({...o, [fld]: obj[fld]}), {})

const groupAndMerge = (groupFields, mergeFields, xs) => 
  Object.values(xs.reduce(
    (a, x, _, __, key = JSON.stringify(pick(groupFields, x))) => 
      (a[key] = (a[key] || []).concat(x)) && a,
    {}
  )).map(xs => ({
    ...xs[0],
    ...mergeFields.reduce((a, f) => ({...a, [f]: xs.map(x => x[f])}), {})
  }))

const myValues = [{arrangeid: "FIREFOX", client: "FIRE", firstname: "Test", fid: "test@fire.com", region: "FOP", secondname: "Testy", status: "Approved"}, {arrangeid: "BUZZZZZZ", client: "FIRE", firstname: "Test", fid: "test@fire.com", region: "FOP", secondname: "Testy", status: "Approved"}, {arrangeid: "PANTER", client: "PANTER", firstname: "Panty", fid: "panty@panter.com", region: "PAN", secondname: "mc panty", status: "Approved"}, {arrangeid: "BLACKBAT", client: "BAT", firstname: "Bruce", fid: "bat@bat.com", region: "BLK", secondname: "Wyne", status: "Approved"}]

const result = groupAndMerge(['client', 'id'], ['arrangeid'], myValues)

console.log(result)

辅助函数pick只是选择目标对象的某些属性,因此pick(['a', 'c'], {a: 1, b: 2, c: 3}) //=> {a: 1, c: 3}

groupAndMerge使用第一个参数(此处为['client', 'id'])来标识必须相同的字段,使用第二个参数(此处为['arrangeid'])来显示必须相同的字段分组。

您提到前两个具有相同的id。我的代码同时检查clientid;这和概念验证一样多,但可能很有用。

有一个使用此警告的注意事项:它只能在字符串或数字值上很好地合并。其他一些可能会工作,但我不会指望它。 (这里至少有一个答案也是如此,但我不知道这对您是否重要。)

我看到的优点是,它仅比定制实现稍微复杂一些,并且在许多其他情况下很有用。