如何比较数组元素并根据条件合并?

4

我有如下示例数组。(原始数组有超过200个元素)

var array = [
  {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwLL9hHP938H",
    "groupname": "ABC",
    "ancestorid": "8982857550",
    "stroyid": [
      "IGN-EXM-001-PDF",
      "IGN-EXM-002-PDF"
    ]
  }, {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwpHOD4aTP38H",
    "groupname": "EFG",
    "ancestorid": "4705872914",
    "stroyid": [
      "APP-ENE-FIE-CON",
      "APP-ENE-ASS-INS",
      "APP-ENE-ASS-CAR",
      "APP-ENE-MAT-REA"
    ]
  }, {
    "clientid": "ID000002",
    "accesstoken": "pllALEl3TlwLL9hHP938H",
    "groupname": "ABC",
    "ancestorid": "8982857550",
    "stroyid": [
      "IGN-EXM-001-ZIP",
      "IGN-EXM-002-ZIP"
    ]
  }
]

条件 = 如果 (客户端id和祖先id相同,则合并storyid),因此输出应该如下:

[{
  "clientid": "ID000002",
  "accesstoken": "pllALEl3TlwLL9hHP938H",
  "groupname": "ABC",
  "ancestorid": "8982857550",
  "stroyid": [
    "IGN-EXM-001-PDF",
    "IGN-EXM-002-PDF",
    "IGN-EXM-001-ZIP",
    "IGN-EXM-002-ZIP"

  ]
}, {
  "clientid": "ID000002",
  "accesstoken": "pllALEl3TlwpHOD4aTP38H",
  "groupname": "EFG",
  "ancestorid": "4705872914",
  "stroyid": [
    "APP-ENE-FIE-CON",
    "APP-ENE-ASS-INS",
    "APP-ENE-ASS-CAR",
    "APP-ENE-MAT-REA"
  ]
}]

请帮我设计JavaScript代码来实现这个功能。

你的示例合并了两个具有不同ID的条目。 - user5183133
@user3742114 谢谢 - James_RajKumar
不同的“accesstoken”在分组结果中应该发生什么? - Nina Scholz
如果ID和祖先ID匹配,访问令牌将是相同的。 - James_RajKumar
4个回答

3

使用纯Javascript,您可以使用哈希表作为闭包来根据clientidancestorid进行分组。

stroyid将被过滤为唯一值。

var array = [{ clientid: "ID000002", accesstoken: "pllALEl3TlwLL9hHP938H", groupname: "ABC", ancestorid: "8982857550", stroyid: ["IGN-EXM-001-PDF", "IGN-EXM-002-PDF", "dupe"] }, { clientid: "ID000002", accesstoken: "pllALEl3TlwpHOD4aTP38H", groupname: "EFG", ancestorid: "4705872914", stroyid: ["APP-ENE-FIE-CON", "APP-ENE-ASS-INS", "APP-ENE-ASS-CAR", "APP-ENE-MAT-REA"] }, { clientid: "ID000002", accesstoken: "pllALEl3TlwLL9hHP9n", groupname: "ABC", ancestorid: "8982857550", stroyid: ["IGN-EXM-001-ZIP", "IGN-EXM-002-ZIP", "dupe"] }],
    result = array.reduce(function (hash) {
        return function (r, a) {
            var key = [a.clientid, a.ancestorid].join('|');
            if (!hash[key]) {
                hash[key] = { clientid: a.clientid, accesstoken: a.accesstoken, groupname: a.groupname, ancestorid: a.ancestorid, stroyid: a.stroyid };
                return r.concat(hash[key]);
            }
            hash[key].stroyid = hash[key].stroyid.concat(a.stroyid).filter(function (temp) {
                return function (a) {
                    return !temp[a] && (temp[a] = true);
                };
            }(Object.create(null)));
            return r;
        };
    }(Object.create(null)), []);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }


非常感谢,它起作用了。还有一件事,是否可以删除故事ID中的重复值? - James_RajKumar

1

const myArray = [
  { clientid: 1, ancestorid: 1, stroyid: ['a', 'b', 'c'] },
  { clientid: 1, ancestorid: 1, stroyid: ['a', 'b', 'd', 'e'] },
];

const newArray = myArray.reduce((newArray, entry) => {
  // Find if there is a duplicate in the new array
  const duplicate = newArray.find(newEntry => (
    entry.clientid === newEntry.clientid && entry.ancestorid === newEntry.ancestorid
  ));

  // If there is a duplicate, merge their stroyids
  if (duplicate) {
    const cleanIDs = entry.stroyid.filter(id => !duplicate.stroyid.includes(id));
    duplicate.stroyid = duplicate.stroyid.concat(cleanIDs);
  }
  else newArray.push(entry); // Else, add the entire entry

  return newArray;
}, []);

console.log(newArray);


嘿,谢谢。我正在使用Node.js工作,但是我遇到了这个错误 => array.reduce((newArray, entry) => { ^ SyntaxError: 意外的令牌 > - James_RajKumar
@user3742114 现在应该已经修复了,请尝试运行代码片段。 - user5183133

1

你可以通过迭代数组并基于合并条件的唯一组合将结果添加到 Map 中来处理此问题。例如,使用 ID 的连接应该可以工作。

如果 Map 已经有一个对象作为其键的条件,我们就会将当前项与值合并,否则,我们会添加它。

代码的一个瓶颈是你还需要深度合并这些对象,这在 JavaScript 中不受支持,超出了此问题的范围。你可以查看 this SO thread

这里是一个示例(我使用 deepmerge 库进行合并):

var array=[{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP938H",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-PDF","IGN-EXM-002-PDF"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwpHOD4aTP38H",groupname:"EFG",ancestorid:"4705872914",stroyid:["APP-ENE-FIE-CON","APP-ENE-ASS-INS","APP-ENE-ASS-CAR","APP-ENE-MAT-REA"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP9n",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-ZIP","IGN-EXM-002-ZIP"]}];
    
const map = new Map();
const mergeKey = ({ clientid, ancestorid }) => `${clientid}${ancestorid}`;

for (const item of array) {
  const key = mergeKey(item);
  if (map.has(key)) {
    map.set(key, deepmerge(map.get(key), item));
  } else {
    map.set(key, item);
  }
}

const merged = Array.from(map.values());
console.log(merged);
<script src="https://unpkg.com/deepmerge@1.3.2/index.js"></script>

如有需要,ES5版本:

var array=[{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP938H",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-PDF","IGN-EXM-002-PDF"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwpHOD4aTP38H",groupname:"EFG",ancestorid:"4705872914",stroyid:["APP-ENE-FIE-CON","APP-ENE-ASS-INS","APP-ENE-ASS-CAR","APP-ENE-MAT-REA"]},{clientid:"ID000002",accesstoken:"pllALEl3TlwLL9hHP9n",groupname:"ABC",ancestorid:"8982857550",stroyid:["IGN-EXM-001-ZIP","IGN-EXM-002-ZIP"]}];
    
var map = Object.create(null);
function mergeKey(item) {
  return item.clientid + item.ancestorid;
}

array.forEach(function(item) {
  var key = mergeKey(item);
  if (map[key]) {
    map[key] = deepmerge(map[key], item);
  } else {
    map[key] = item;
  }
});

var merged = Object.keys(map).map(function(key) {
  return map[key];
});
console.log(merged);
<script src="https://unpkg.com/deepmerge@1.3.2/index.js"></script>


我在node.js中遇到了这个错误 => const mergeKey = ({ clientid, ancestorid }) => ${clientid}${ancestorid}; ^ 语法错误:意外的标记“,”。 - James_RajKumar
@user3742114 可能是因为你的 Node 版本不支持 ES6 解构赋值。我也添加了一个 ES5 版本。 - nem035

1
您可以使用以下方法合并storyId,并去除重复项,然后用原始的storyId数组替换它:
if(array[0].clientid == array[1].clientid && array[0].ancestorid == array[1].ancestorid){
var c = array[0].stroyid.concat(array[1].stroyid.filter(function (item) {
    return array[0].stroyid.indexOf(item) < 0;
}));
}

Ahmad,请提供for循环代码,我无法得到所需的输出。我已经在我的帖子中更新了数组。 - James_RajKumar

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