我有3个阵列:
array1 = [ 'A', 'B', 'A', 'B']
array2 = [ 5, 5, 7, 5]
array3 = [true,true,true,true]
我想知道是否有任何简单的方法(可能使用lodash)来消除重复并以此结束:
array1 = [ 'A', 'B', 'A']
array2 = [ 5, 5, 7]
array3 = [true,true,true]
我知道我可以做一个函数并比较之前的值,但是有更聪明的方法吗?
更新 请注意,我不需要消除每个数组的重复项。 我所期待的是一种消除重复“垂直”的方法
更新2
请注意,每个“列”都是一个记录。
record1 = ['A',5,true]
record2 = ['B',5,true]
record3 = ['A',7,true]
record1 = ['B',5,true]
答案 0 :(得分:4)
const records = array1.map((a, i) => [a, array2[i], array3[i]]);
const index = {};
records.filter(column => {
const key = JSON.stringify(column);
return key in index ? false : index[key] = true;
});
有很多方法可以解决这个问题,效率会有不同程度,最佳解决方案取决于数据的大小。一个简单但天真的解决方案遍历每个“列”并检查所有前面的列是否相等。它看起来像这样:
const array1 = [ 'A', 'B', 'A', 'B'];
const array2 = [ 5, 5, 7, 5];
const array3 = [true,true,true,true];
const newArray1 = array1.slice(0,1); // column 0 is never duplicate
const newArray2 = array2.slice(0,1);
const newArray3 = array3.slice(0,1);
// loop over columns starting with index 1
outer: for (let i = 1; i < array1.length; i++) {
const a = array1[i];
const b = array2[i];
const c = array3[i];
// check all preceding columns for equality
for (let j = 0; j < i; j++) {
if (a === array1[j] && b === array2[j] && c === array3[j]) {
// duplicate; continue at top of outer loop
continue outer;
}
}
// not a duplicate; add to new arrays
newArray1.push(a);
newArray2.push(b);
newArray3.push(c);
}
console.log(newArray1);
console.log(newArray2);
console.log(newArray3);
.as-console-wrapper{min-height:100%}
如您所见,我们必须每次检查每列中的每一行是否相等。如果你很好奇,那么它的复杂性是((+1)/ 2)(技术上((+ 1)/ 2),其中三列为3)。
对于更大的数据集,跟踪您在快速访问的数据结构中已经看到的值是有利的:哈希,a.k.a.JavaScript对象。由于您的所有值都是原始值,因此构造键的快速方法是JSON.stringify
。有些人可能认为这是“黑客” - 重要的是要注意它将失败,其值不能用JSON表示,例如Infinity
或NaN
- 但这是一个简单快捷的数据。
const array1 = ['A', 'B', 'A', 'B'];
const array2 = [5, 5, 7, 5];
const array3 = [true, true, true, true];
const newArray1 = [];
const newArray2 = [];
const newArray3 = [];
const index = {};
for (let i = 0; i < array1.length; i++) {
const a = array1[i];
const b = array2[i];
const c = array3[i];
const key = JSON.stringify([a,b,c]);
if (key in index) {
// duplicate; skip to top of loop
continue;
}
// not a duplicate; record in index and add to new arrays
index[key] = true;
newArray1.push(a);
newArray2.push(b);
newArray3.push(c);
}
console.log(newArray1);
console.log(newArray2);
console.log(newArray3);
.as-console-wrapper{min-height:100%}
这的复杂性是(),或者可能是(2)再次,
三列是3,而另一个是非常粗略地考虑JSON.stringify
的成本。 (弄清楚哈希访问的成本留给我们中的学生练习;我满足于称之为(1)。)
这仍然非常冗长。部分原因是对数据使用三个不同的变量 - 这实际上是一个单独的“表” - 导致大量重复。我们可以预处理数据,以便更容易处理。一旦它“转换”成一个二维数组,我们可以使用Array.prototype.filter
和上面的关键技术,对于一些非常简洁的代码:
const array1 = ['A', 'B', 'A', 'B'];
const array2 = [5, 5, 7, 5];
const array3 = [true, true, true, true];
// turn "columns" into "rows" of a 2D array
const records = array1.map((a, i) => [a, array2[i], array3[i]]);
const index = {};
const newData = records.filter(column => {
const key = JSON.stringify(column);
return key in index ? false : index[key] = true;
});
console.log(newData);
.as-console-wrapper{min-height:100%}
当然,预处理不是免费的,所以这个代码不比更详细的版本更高效;你必须决定对你有多重要。如果您愿意,现在可以将newData
中的列提取为三个变量(newData.forEach(([a,b,c]) => { newArray1.push(a); newArray2.push(b); /* ... */ })
),但出于多种目的,“转置”2D数组将更易于使用。
答案 1 :(得分:2)
您可以使用ES6设置https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
设置 - &gt;允许您存储任何类型的唯一值,无论是原始值还是对象引用。
然后转换回数组
检查此代码段
const array1 = ['A','B','A','B']
const array2 = [5,5,7,5]
const array3 = [true,true,true,true]
const uniqA1= new Set(array1)
const uniqA2= new Set(array2)
const uniqA3= new Set(array3)
console.log(Array.from(uniqA1))
console.log(Array.from(uniqA2))
console.log(Array.from(uniqA3))
希望有所帮助
答案 2 :(得分:1)
您需要在所有数组中找到具有相同索引的重复元素,然后过滤掉这些元素。
echo
&#13;
答案 3 :(得分:1)
你需要一些辅助函数(lodash也提供它们):
let zip = (...arys) => arys[0].map((_, i) => arys.map(a => a[i]));
let uniq = (ary, key) => uniq2(ary, ary.map(key), new Set);
let uniq2 = (ary, keys, set) => ary.filter((_, i) => !set.has(keys[i]) && set.add(keys[i]))
// test
var array1 = ['A', 'B', 'A', 'B'];
var array2 = [5, 5, 7, 5];
var array3 = [true, true, true, true];
var [x, y, z] = zip(
...uniq(
zip(array1, array2, array3),
JSON.stringify
)
);
console.log(x, y, z)
答案 4 :(得分:0)
另一种方式,filter():
array1 = ['A', 'B', 'A', 'B'];
array2 = [5, 5, 7, 5];
array3 = [true, true, true, true];
uniqueArray1 = array1.filter(function(item, pos) {
return array1.indexOf(item) == pos;
})
uniqueArray2 = array2.filter(function(item, pos) {
return array2.indexOf(item) == pos;
})
uniqueArray3 = array3.filter(function(item, pos) {
return array3.indexOf(item) == pos;
})
console.log(uniqueArray1);
console.log(uniqueArray2);
console.log(uniqueArray3);
&#13;
答案 5 :(得分:0)
这是一个很好的方法,已经回答了here
var arr = ["apple", "bannana", "orange", "apple", "orange"];
arr = arr.filter( function( item, index, inputArray ) {
return inputArray.indexOf(item) == index;
});
---------------------
Output: ["apple", "bannana", "orange"]
答案 6 :(得分:0)
我能想到的一种方法是使用一个对象来跟踪,这也会巧合地删除任何重复项,因为键必须是唯一的。唯一的问题是我现在可以想到如何将它提取回数组。我明天会考虑的。
这利用jquery进行深度克隆。如果你只想在vanilla javascript中使用它,你可能只需要实现深度克隆功能。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
; (INPUT)
; data = 1-D array of intensities
; (OUTPUT)
; bck,sig = background and fluctuations (1 sig level)
; ndata = number of values upon which bck,sig are computed
; POSITIVE = retains only data values > 0
; NSIG = number of sigmas
if not(keyword_set(NSIG)) then nsig=3.
if keyword_set(POSITIVE) then begin
test=where(data gt 0.)
if test(0) ne -1 then data2=data(test) else begin
bck=0 & sig=-1 & ndata=0 & goto,out
endelse
endif else data2=data
if n_elements(data2) gt 1 then begin
bck=mean(data2,/double) & sig=stddev(data2,/double)
endif else begin
bck=data2(0) & sig=0 & ndata=1 & goto,out
endelse
ndata=1
loop:
test=where(abs(data2-bck) lt nsig*sig)
if n_elements(test) eq 1 then goto,out
ndata=n_elements(test)
moy=mean(data2(test),/double)
sig=stddev(data2(test),/double)
if moy eq bck then goto,out
bck=moy
goto,loop
out:
return
end