合并数组,仅添加新元素

4

嘿,我一直在为一些应该很简单的事情苦恼。我有几个数组:

//input

var array1 = ["white", "white", "yellow"];
var array2 = ["white", "white", "yellow", "red"];
var array3 = ["white", "white", "yellow", "orange"];

//desired output

var result = ["white", "white", "yellow", "red", "orange"];

这应该是一个简单的问题,但我一直无法理解它。我尝试使用第一个数组的快照,然后查看颜色是否已经在快照数组中,将其从快照中移除,放入另一个快照等等…但最终我得到了很多代码。我甚至无法使它正常工作,因为我正在从快照中删除所有“白色”颜色而不仅仅是一个,并且其他事情也出了问题。
有人可以给我第二个角度吗?因为我现在卡壳了。
我最后一次尝试被要求提供代码。
    let attacks = entry.attacks;
    if(attacks !== undefined){
        let lastSnapshot = [];

        attacks.forEach(attack => {
            if(lastSnapshot.length === 0){
                attack.forEach(attackColor => {
                    lastSnapshot.push(attackColor)
                })                        
            }else{
                let newSnapshot = [];
                attack.forEach(attackColor => {
                    var start_index = lastSnapshot.findIndex(attackColor)
                    if(start_index !== -1){
                        var number_of_elements_to_remove = 1;
                        lastSnapshot.splice(start_index, number_of_elements_to_remove);                                
                    }

                    newSnapshot.push(attackColor)
                })
                lastSnapshot = newSnapshot;                              
            }
        })
    }

输出应该像这样 var result = ["white", "yellow", "red", "orange"]; 为什么在数组内重复使用 while 值? - A l w a y s S u n n y
数组的数量可以增加到3个。 - Helping hand
看一下这个:https://dev59.com/BHI-5IYBdhLWcg3w-9wK#1584377 - Sølve T.
顺序重要吗? - charlietfl
@charlieftl,顺序并不重要。 - kenny
显示剩余5条评论
2个回答

4
你可以使用 reduce 来处理数组,对于数组中的单个元素,可以使用 forEach 来添加元素到 r 中。
然后使用哈希表来存储已访问的元素及其在临时结果数组 r 中的最后索引。如果未找到任何元素,则将实际值推送到数组中。

var array1 = ["white", "white", "yellow"],
    array2 = ["white", "white", "yellow", "red"],
    array3 = ["white", "white", "yellow", "orange"],
    result = [array1, array2, array3].reduce((r, a) => {
        var indices = Object.create(null);
        a.forEach(b => {
            var p = r.indexOf(b, indices[b] || 0);
            indices[b] = p === -1 ? r.push(b) : p + 1;
        });
        return r;
    });
    
console.log(result);


var p = r.includes(b); if (!p) { r.push(b); } else { indices[b] = p; } 对我来说更容易阅读,我相信它也能达到同样的效果。 - StudioTime
我需要找到的项的索引以进行下一次搜索。 - Nina Scholz
1
@NinaScholz 我对这个问题的概念不是很清楚,你能否给我一些提示,关于何时应该使用 Object.create(null) 而不是 {} - Nishant Dixit
1
我不得不盯着那个东西一段时间才弄明白,但它真的很棒。+1 - Mark
1
Object.create(null) 创建一个真正没有原型的空对象,例如 toString。使用这个空对象,如果值为 toString,可以将其用于缓存索引。普通对象 {} 对于所有键都不适用,因为它包含原型。决定何时使用空对象而不是普通对象主要取决于预期的值。如果不确定,请使用空对象以保险起见。 - Nina Scholz
显示剩余3条评论

1
你也可以尝试使用 SetSpreadforEach 来实现。

var array1 = ["white", "white", "yellow"];
var array2 = ["white", "white", "yellow", "red"];
var array3 = ["white", "white", "yellow", "orange"];
var merged = Array.from(new Set(array2.concat(array3)));
var desired = [...array1];
merged.forEach(function(element, index) {
  if (array1.indexOf(element) == -1) {
    desired.push(element);
  }
})
console.log(desired)

展开语法: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax

Set集合: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Set

forEach循环: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach


谢谢,你的代码可行,幸运的是我可以在我的小项目中使用扩展操作符。然而,Nina Scholz的代码也很好用,她正在使用原生JavaScript。我觉得应该把正确的答案给她……希望你不介意。 - kenny
@kenny 没关系,因为我从 Nina Scholz 在 SO 上学到了很多东西,她是我在 JS 方面的偶像。很高兴它在某种程度上对你有所帮助。祝你好运。顺便说一句: 我的版本也是纯JS :) - A l w a y s S u n n y
这是什么意思?因为当我使用...运算符时,我需要将以下内容添加到我的项目中:"plugins": [ "transform-async-to-generator", "transform-class-properties", "transform-object-rest-spread" ],顺便说一句:我是一名Java开发人员,正在学习React JavaScript,所以有很多东西对我来说还不明显。 - kenny
1
请添加以下内容作为 var array2 = ["white", "white", "yellow", "red", "red"]; 并尝试您的算法。看起来,它从未添加第二个 "red",因为您只是使用了 includes 进行检查。 - Nina Scholz

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