如何使用相同的键匹配和合并两个对象数组

时间:2019-07-16 01:39:34

标签: javascript merge

给出以下对象数组:

old = [{x:1, y:100}, {x:2, y:5}, {x:3, y:400}] 
update = [{x:1, y:5}, {x:3, y:0}]

old应该更新: 如果x旧匹配x更新:y旧应该更新,

如果更新的y为0,则应从旧数组中删除x old的对象。

我的方法

let merge = (update, old) => {
  for(let I of update) {
    let K = old.findIndex(J => J.x== I.x)

    (K === -1 && I.y != 0) && old.push(I)

    (K >= 0) && (old[K] = I) && ((old[K].y== 0) && old.splice(K,1))

  }
}

是否有使用地图过滤器精简或散布算子的专家?最好在这里做什么?有快捷方式(语法糖)吗?

2 个答案:

答案 0 :(得分:0)

如果性能很重要,那么一个有趣的问题是两个数组是否已排序。如果是的话,您可以通过两种方式循环进行合并排序中的合并,并以O(n)而不是O(n ^ 2)进行。

如果没有x的重复项,我会考虑使用Set而不是数组。

要将数组转换为集合,可以执行以下操作:

const map = arr.reduce((m, v) => m.set(m.x, m.y), new Map());

使用Map时,get的性能可能会好于使用find时的数组(最好是O(n log n)。

现在,只要有保证,新数组中的每个元素也都在旧数组中就很容易了:

new Map([...oldMap.entries(), ...newMap.entries()]);

这是因为Map接受一个由两个元素组成的数组,其中第一个是键,第二个是值。而且,如果您两次通过密钥,第二秒将获胜,这就是您的覆写。

现在,如果您不想要地图,但是原来的结构,则来回转换的整个过程看起来像这样:

function merge(update, old) {
  const toMap = arr => arr.map(e => [e.x, e.y]);
  return new Map([...toMap(old), ...toMap(update)])
    .entries()
    .map(([x, y]) => ({ x, y }));
}

答案 1 :(得分:0)

您需要指定更多的意外情况。由于update.length只有2,我们如何处理old [2]上的对象? 另外,您的条件:

  

“如果y的更新值为0,则应从旧数组中删除x old的对象”

有点不清楚。如果可能,请尝试使用点符号,因为这里的每个人都可能会更好地理解这一点。

无论如何,这是我的看法,尽管可能是我误解了需要满足的条件。 我假设索引> = update.length时old [index]处的值应按原样返回。


const result = old.map( ( value, index ) => {
    if ( update[index] ){
        if ( update[index].y === 0 ) return null
        if ( value.x === update[index].x ) {
            return {
                x: value.x,
                y: update[index].y
            }
        }
    }
    return value
} ).filter( value => value )

这将产生以下输出:

[
  { x: 1, y: 5 },
  { x: 3, y: 400 }
]