【问题标题】:Javascript - Mix two arrays of objects ordering by date and without repetitionsJavascript - 混合两个按日期排序且不重复的对象数组
【发布时间】:2022-01-02 15:46:26
【问题描述】:

我有两个列表:

let originalDocs = [
  {
    id: "sara",
    date: new Date("01/01/2022")
  },
  {
    id: "vic",
    date: new Date("10/26/2020")
  }
];

let newDocs = [
   {
     id: "vic",
     date: new Date("01/02/2022")
   },
   {
     id: "raul",
     date: new Date("05/05/2021")
   }
];

我需要混合两个列表,按日期排序(按降序排列)并且不重复。

为了做到这一点,我决定:

  1. 删除原始数组中包含在新数组中的元素集(我的意思是删除交集)而不修改原始数组。
  2. 按日期混合结果数组排序。

这是我当前的代码:

function removeIntersection(originalDocs, newDocs) {
  return  originalDocs.filter((originalDoc) => {
    const index = newDocs.findIndex(
      (newDoc) => newDoc.id === originalDoc.id
    );

    return index === -1;
  });
}

function mixInOrder(originalDocs, newDocs) {
   return [...newDocs, ...originalDocs]
    .sort((a, b) => b.date - a.date);
}


//
// MAIN
//

let originalDocs = [
  {
    id: "sara",
    date: new Date("01/01/2022")
  },
  {
    id: "vic",
    date: new Date("10/26/2020")
  }
];

let newDocs = [
  {
    id: "vic",
    date: new Date("01/02/2022")
  },
  {
    id: "raul",
    date: new Date("05/05/2021")
  }
];

const result = mixInOrder(
  removeIntersection(originalDocs, newDocs),
  newDocs
);

console.log(result);

我怎样才能以更优化的方式做同样的事情,我的意思是,在排序之前不需要合并(使用扩展语法)列表,或者删除 O(1) 中的交集。

我的意思是,是否可以只插入以避免复制?

【问题讨论】:

  • 如果两个数组中都存在一个id相同的项,你想保留哪一个?
  • @tao 在示例 sn-p 中,OP 从newDocs 获取一个项目
  • @tao,第二个列表“newDocs”中的那个。
  • @404,upsss,我的意思是删除交集但不修改这个数组。我在减速器中执行这段代码,所以我不能修改它。

标签: javascript algorithm


【解决方案1】:

您可以使用Set 和reduce 轻松实现结果:

  • 首先添加originalDocs,然后添加newDocs,从而创建一个新数组。
  • 使用reduce 循环遍历新创建的数组,然后过滤对象。

您可以使用Set 以有效的方式检查密钥是否存在

  • 过滤后,您可以对其进行相应的排序。

let originalDocs = [
  {
    id: 'sara',
    date: new Date('01/01/2022'),
  },
  {
    id: 'vic',
    date: new Date('10/26/2020'),
  },
];

let newDocs = [
  {
    id: 'vic',
    date: new Date('01/02/2022'),
  },
  {
    id: 'raul',
    date: new Date('05/05/2021'),
  },
];

const set = new Set();
const result = [...originalDocs, ...newDocs].reduce((acc, curr) => {
    if (!set.has(curr.id)) {
      acc.push(curr);
      set.add(curr.id);
    }
    return acc;
  }, [])
  .sort((a, b) => b.date - a.date);
console.log(result);

【讨论】:

    【解决方案2】:

    以下是使用 JS Map 的方法,您使用 id 作为标识符:

    let originalDocs = [
      {
        id: "sara",
        date: new Date("01/01/2022")
      },
      {
        id: "vic",
        date: new Date("10/26/2020")
      }
    ];
    
    let newDocs = [
      {
        id: "vic",
        date: new Date("01/02/2022")
      },
      {
        id: "raul",
        date: new Date("05/05/2021")
      }
    ];
    const map = new Map(originalDocs.map(el => [el.id, el]));
    newDocs.forEach(el => map.set(el.id, el));
    const sorted = [...map.values()].sort((a, b) => a.date - b.date);
    console.log(sorted)

    如果 originalDocs 具有相同的 id 条目,这将使用 newDocs 条目覆盖任何 originalDocs 条目。

    【讨论】:

    • 每次迭代都使用 findIndex 永远不会是最佳方法
    • 我认为findIndex 很快。什么是最佳方法?
    • 使用 id 作为键创建 Map 或对象会更加高效,因为查找是 o(1) 而 findIndex 是 o(n)
    • 所以你是说最有效的方法是将它们合并,然后将order 合并到一个新副本中?
    • 应该是 b.date - a.date(排序时)
    猜你喜欢
    • 2017-05-21
    • 2014-09-08
    • 1970-01-01
    • 2015-02-25
    • 2021-06-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多