简体   繁体   English

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

[英]How to match and merge two arrays of objects with same keys

Given the following Arrays of Objects: 给定以下对象数组:

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

old should be updated: if x old matches x update: y old should be updated, 应该更新旧的:如果x旧匹配x更新:y旧应该更新,

if y of update is 0, the object of x old should be removed from the old array. 如果更新的y为0,则应从旧数组中删除x old的对象。

My approach 我的方法

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))

  }
}

Any experts in using map filter reduce or spread operator? 有任何使用地图过滤器的专家来简化或扩展运算符? What is the best to do here? 最好在这里做什么? Is there a shortcut method (syntax sugar)? 有快捷方式(语法糖)吗?

If performance matters an interesting question is if the two arrays are sorted. 如果性能很重要,那么一个有趣的问题是两个数组是否已排序。 If yes you can just loop through both the same way a merge in merge sort works and do it in O(n) instead of O(n^2). 如果是,则可以通过两种方式循环并入合并排序,并以O(n)而不是O(n ^ 2)的方式进行。

If you have no duplicates of x I would consider using Set s instead of arrays. 如果没有x重复项,我会考虑使用Set而不是数组。

To transform the array to a set you can do: 要将数组转换为集合,可以执行以下操作:

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

a Map will likely have a better performance when using get then a array when using find (which at best is O(n log n). 使用get时, Map可能会具有更好的性能,而使用find ,其性能可能最好是O(n log n)。

Now if you have a guarantee, that every element in the new array is also in the old array its easy: 现在,如果可以保证,新数组中的每个元素也都在旧数组中就很容易了:

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

this is because Map takes an array of two-element array where the first is the key and the second is the value. 这是因为Map接受一个由两个元素组成的数组,其中第一个是键,第二个是值。 And if you pass a key twice the second will win, so thats your overwriting. 而且,如果您两次通过密钥,第二秒将获胜,这就是您的覆写。

Now if you dont want maps but your original structure the entire thing with converting back and forth could look like this: 现在,如果您不想要地图,但想要原始结构,则来回转换的整个过程可能如下所示:

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 }));
}

You need to specify more contingencies. 您需要指定更多的意外情况。 What do we do for the object at old[2], since update.length is only 2? 由于update.length只有2,我们如何处理old [2]上的对象? Also, your condition: 另外,您的条件:

"if y of update is 0, the object of x old should be removed from the old array" “如果更新的y为0,则应从旧数组中删除x old的对象”

is a bit unclear. 还不清楚。 Try using dot-notation if possible, as this is probably better understood by everyone here. 如果可能,请尝试使用点符号,因为这里的每个人都可能会更好地理解。

Anyways, here's my take, though it's possibly I misunderstood the conditions that need to be satisfied. 无论如何,这是我的看法,尽管可能是我误解了需要满足的条件。 I assumed that a value at old[index] when index >= update.length should just be returned as-is. 我假设索引> = 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 )

This yeilds the following output: 这将产生以下输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM