如何简化基于属性组合两个数组的es6函数?

时间:2016-10-08 10:11:32

标签: javascript arrays ecmascript-6

我有两个数组,一个现有的集合和一个新的数组。我想以下列方式将两者结合起来:

  • 从现有对话中的所有元素开始
  • 对于新数组中的每个项目,如果现有数组中不存在具有相同id的元素,则我们将添加它。
  • 如果项目确实存在且具有相同的id,那么只有当新项目的updated属性的值大于updated的值时,才会替换现有项目现有财产。
  • 如果它不大于我们只是忽略新元素。

我们不能修改传入的数组,我们必须返回组合数组。

function combineConversations(newConversations, existingConversations) {
  const combined = [...existingConversations];
  newConversations.forEach(conversation => {
    const existingConversationIndex = indexOfObject(combined, conversation.id , 'id');
    if (existingConversationIndex && conversation.updated > combined[existingConversationIndex].updated) {
      combined[existingConversationIndex] = conversation;
    } else {
      combined.push(conversation);
    }
  });
  return combined;
}

我想知道一个完整的功能方法来做到这一点。有吗?

3 个答案:

答案 0 :(得分:1)

是的,您可以使用这样的功能方法来实现:

var oldChat = [
  {id: 1, updated: 1985, data: "coucou"},
  {id: 2, updated: 1995, data: "au revoir"},
  {id: 3, updated: 2003, data: "bonjour"}
];

var newChat = [
  {id: 1, updated: 1986, data: "coucou"},
  {id: 2, updated: 2004, data: "bye"},
  {id: 3, updated: 2001, data: "bonjour"},
  {id: 4, updated: 2008, data: "vive le sport"}
];

var result = (oldChat, newChat) => newChat.concat(oldChat).sort((a,b) => a.id-b.id).filter((item, index, arr) => index < arr.length - 1 ? item.id !== arr[index+1].id : true);
console.log(result(oldChat, newChat)); //[ { id: 1, updated: 1986, data: 'coucou' },
//{ id: 2, updated: 2004, data: 'bye' },
//{ id: 3, updated: 2003, data: 'bonjour' },
//{ id: 4, updated: 2008, data: 'vive le sport' } ]

编辑:我合并了旧的和新的数组并对它们进行了排序以获得具有相同ID的相邻元素,然后进行过滤以保留那些具有唯一ID或最新更新的元素

答案 1 :(得分:1)

这是解决问题的另一种方法(我使用@kevinternet示例,希望他不介意):

var oldChat = [
  {id: 1, updated: 1985, data: "coucou"},
  {id: 2, updated: 1995, data: "au revoir"},
  {id: 3, updated: 2003, data: "bonjour"}
];

var newChat = [
  {id: 1, updated: 1986, data: "coucou"},
  {id: 2, updated: 2004, data: "bye"},
  {id: 3, updated: 2001, data: "bonjour"},
  {id: 4, updated: 2008, data: "vive le sport"}
];

var intersect = oldChat.reduce((memo, val) => memo.concat(newChat.find(v => val.id === v.id && val.updated < v.updated) || val), []);
var diff = newChat.filter(x => !oldChat.some(y => y.id === x.id));

console.log(intersect.concat(diff));

这个想法是:

  1. 将两个数组相交。这是一个特殊的交集:如果比较的元素具有相同的ID,我们必须采取更新的更新,以便find具有特殊条件,新元素必须比旧元素更新,否则,我们还没有找到正确的更换。
  2. 我们必须处理oldChatnewChat之间不常见的元素。由于我们执行了从oldChatnewChat的特殊交集(这保证oldChat中的所有对象都将在新的对象中),我们执行与newChatoldChat
  3. Concat与差异的特殊交叉点,以获得所需的结果。
  4. 希望它有所帮助。

答案 2 :(得分:0)

我明白了!

function combineConversations(myArr) {
  return myArr.filter((item1, pos, arr) =>
    arr.map(item2 => item1.id === item2.id && item1.updated === item2.updated).indexOf(true) === pos &&
    arr.every(item2 => !(item1 !== item2 && item1.id === item2.id && item1.updated < item2.updated))
  );
}
combineConversations([...newChat, ...oldChat]);

var oldChat = [
  {id: 1, updated: 1985, data: "coucou"},
  {id: 2, updated: 1995, data: "au revoir"},
  {id: 3, updated: 2003, data: "bonjour"},
  {id: 4, updated: 2016, data: "hallo"},
];

var newChat = [
  {id: 1, updated: 1986, data: "coucou"},
  {id: 2, updated: 2004, data: "bye"},
  {id: 3, updated: 2001, data: "bonjour"},
  {id: 5, updated: 2008, data: "vive le sport"}
];

var expected = [
  {id: 1, updated: 1986, data: "coucou"},
  {id: 2, updated: 2004, data: "bye"},
  {id: 3, updated: 2003, data: "bonjour"},
  {id: 4, updated: 2016, data: "hallo"},
  {id: 5, updated: 2008, data: "vive le sport"}
];

感谢@ kevin-ternet的回答。你让我走上正轨!