【发布时间】:2011-04-07 11:41:15
【问题描述】:
假设我有一个[34, 35, 45, 48, 49] 数组和另一个[48, 55] 数组。如何获得[34, 35, 45, 48, 49, 55] 的结果数组?
【问题讨论】:
标签: javascript arrays
假设我有一个[34, 35, 45, 48, 49] 数组和另一个[48, 55] 数组。如何获得[34, 35, 45, 48, 49, 55] 的结果数组?
【问题讨论】:
标签: javascript arrays
随着带有集合和 splat 运算符的 ES6 的到来(当时仅在 Firefox 中有效,请检查兼容性表),您可以编写以下神秘的一行:
var a = [34, 35, 45, 48, 49];
var b = [48, 55];
var union = [...new Set([...a, ...b])];
console.log(union);
关于这一行的一点解释:[...a, ...b] 连接两个数组,你也可以使用a.concat(b)。 new Set() 用它创建一个集合,从而创建你的联盟。最后一个[...x] 将其转换回数组。
【讨论】:
Array.from(new Set([...a, ...b])) 替换了扩展运算符,它起作用了。
如果您不需要保留订单,并认为45 和"45" 相同:
function union_arrays (x, y) {
var obj = {};
for (var i = x.length-1; i >= 0; -- i)
obj[x[i]] = x[i];
for (var i = y.length-1; i >= 0; -- i)
obj[y[i]] = y[i];
var res = []
for (var k in obj) {
if (obj.hasOwnProperty(k)) // <-- optional
res.push(obj[k]);
}
return res;
}
console.log(union_arrays([34,35,45,48,49], [44,55]));
【讨论】:
Object.keys() 在 2010 年不存在。
i >= 0 可以代替i。
如果你使用库 underscore 你可以这样写
var unionArr = _.union([34,35,45,48,49], [48,55]);
console.log(unionArr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
【讨论】:
我可能在这里浪费时间在一个死线程上。我只需要实现这一点,然后去看看我是否在浪费时间。
我真的很喜欢 KennyTM 的回答。这就是我要解决的问题。将密钥合并到哈希中以自然消除重复项,然后提取密钥。如果你真的有 jQuery,你可以利用它的好东西把它变成一个 2 行问题,然后把它放到一个扩展中。 jQuery 中的 each() 将负责不遍历 hasOwnProperty() 为 false 的项目。
jQuery.fn.extend({
union: function(array1, array2) {
var hash = {}, union = [];
$.each($.merge($.merge([], array1), array2), function (index, value) { hash[value] = value; });
$.each(hash, function (key, value) { union.push(key); } );
return union;
}
});
请注意,两个原始数组都保持不变。然后你这样称呼它:
var union = $.union(array1, array2);
【讨论】:
O(2n) 中工作(由于两个非嵌套的 for 循环而更快),而不是其余的似乎在O(n^2)(慢)时尚。
function unique(arrayName)
{
var newArray=new Array();
label: for(var i=0; i<arrayName.length;i++ )
{
for(var j=0; j<newArray.length;j++ )
{
if(newArray[j]==arrayName[i])
continue label;
}
newArray[newArray.length] = arrayName[i];
}
return newArray;
}
var arr1 = new Array(0,2,4,4,4,4,4,5,5,6,6,6,7,7,8,9,5,1,2,3,0);
var arr2= new Array(3,5,8,1,2,32,1,2,1,2,4,7,8,9,1,2,1,2,3,4,5);
var union = unique(arr1.concat(arr2));
console.log(union);
【讨论】:
如果你想连接两个没有重复值的数组,试试这个
var a=[34, 35, 45, 48, 49];
var b=[48, 55];
var c=a.concat(b).sort();
var res=c.filter((value,pos) => {return c.indexOf(value) == pos;} );
【讨论】:
改编自:https://stackoverflow.com/a/4026828/1830259
Array.prototype.union = function(a)
{
var r = this.slice(0);
a.forEach(function(i) { if (r.indexOf(i) < 0) r.push(i); });
return r;
};
Array.prototype.diff = function(a)
{
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
var s1 = [1, 2, 3, 4];
var s2 = [3, 4, 5, 6];
console.log("s1: " + s1);
console.log("s2: " + s2);
console.log("s1.union(s2): " + s1.union(s2));
console.log("s2.union(s1): " + s2.union(s1));
console.log("s1.diff(s2): " + s1.diff(s2));
console.log("s2.diff(s1): " + s2.diff(s1));
// Output:
// s1: 1,2,3,4
// s2: 3,4,5,6
// s1.union(s2): 1,2,3,4,5,6
// s2.union(s1): 3,4,5,6,1,2
// s1.diff(s2): 1,2
// s2.diff(s1): 5,6
【讨论】:
我喜欢 Peter Ajtai 的 concat-then-unique 解决方案,但代码不是很清楚。这是一个更好的选择:
function unique(x) {
return x.filter(function(elem, index) { return x.indexOf(elem) === index; });
};
function union(x, y) {
return unique(x.concat(y));
};
由于 indexOf 返回第 次出现的索引,我们将其与当前元素的索引(过滤谓词的第二个参数)进行检查。
【讨论】:
您可以使用 jQuery 插件:jQuery Array Utilities
例如下面的代码
$.union([1, 2, 2, 3], [2, 3, 4, 5, 5])
将返回 [1,2,3,4,5]
【讨论】:
kennytm 回答的简短版本:
function unionArrays(a, b) {
const cache = {};
a.forEach(item => cache[item] = item);
b.forEach(item => cache[item] = item);
return Object.keys(cache).map(key => cache[key]);
};
【讨论】:
function unite(arr1, arr2, arr3) {
newArr=arr1.concat(arr2).concat(arr3);
a=newArr.filter(function(value){
return !arr1.some(function(value2){
return value == value2;
});
});
console.log(arr1.concat(a));
}//This is for Sorted union following the order :)
【讨论】:
function unionArrays() {
var args = arguments,
l = args.length,
obj = {},
res = [],
i, j, k;
while (l--) {
k = args[l];
i = k.length;
while (i--) {
j = k[i];
if (!obj[j]) {
obj[j] = 1;
res.push(j);
}
}
}
return res;
}
var unionArr = unionArrays([34, 35, 45, 48, 49], [44, 55]);
console.log(unionArr);
在方法上与 alejandro 的方法有些相似,但要短一些,并且应该适用于任意数量的数组。
【讨论】:
function unionArray(arrayA, arrayB) {
var obj = {},
i = arrayA.length,
j = arrayB.length,
newArray = [];
while (i--) {
if (!(arrayA[i] in obj)) {
obj[arrayA[i]] = true;
newArray.push(arrayA[i]);
}
}
while (j--) {
if (!(arrayB[j] in obj)) {
obj[arrayB[j]] = true;
newArray.push(arrayB[j]);
}
}
return newArray;
}
var unionArr = unionArray([34, 35, 45, 48, 49], [44, 55]);
console.log(unionArr);
【讨论】:
我会先连接数组,然后只返回唯一值。
您必须创建自己的函数才能返回唯一值。既然是好用的功能,不妨add it in as a functionality of the Array。
在您使用数组 array1 和 array2 的情况下,它看起来像这样:
array1.concat(array2) - 连接两个数组array1.concat(array2).unique() - 仅返回唯一值。这里unique() 是您添加到Array 原型的方法。整个事情看起来像这样:
Array.prototype.unique = function () {
var r = new Array();
o: for(var i = 0, n = this.length; i < n; i++)
{
for(var x = 0, y = r.length; x < y; x++)
{
if(r[x]==this[i])
{
continue o;
}
}
r[r.length] = this[i];
}
return r;
}
var array1 = [34,35,45,48,49];
var array2 = [34,35,45,48,49,55];
// concatenate the arrays then return only the unique values
console.log(array1.concat(array2).unique());
【讨论】:
if(r.indexOf(this[i])!==-1) continue; 而不是内部循环和r.push(this[i]) 而不是r[r.length]=this[i]
之前出于同样的原因写过(适用于任意数量的数组):
/**
* Returns with the union of the given arrays.
*
* @param Any amount of arrays to be united.
* @returns {array} The union array.
*/
function uniteArrays()
{
var union = [];
for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
{
eachArgument = arguments[argumentIndex];
if (typeof eachArgument !== 'array')
{
eachArray = eachArgument;
for (var index = 0; index < eachArray.length; index++)
{
eachValue = eachArray[index];
if (arrayHasValue(union, eachValue) == false)
union.push(eachValue);
}
}
}
return union;
}
function arrayHasValue(array, value)
{ return array.indexOf(value) != -1; }
【讨论】:
处理合并单个数组值的简单方法。
var values[0] = {"id":1235,"name":"value 1"}
values[1] = {"id":4323,"name":"value 2"}
var object=null;
var first=values[0];
for (var i in values)
if(i>0)
object= $.merge(values[i],first)
【讨论】:
你可以试试这些:
function union(a, b) {
return a.concat(b).reduce(function(prev, cur) {
if (prev.indexOf(cur) === -1) prev.push(cur);
return prev;
}, []);
}
或
function union(a, b) {
return a.concat(b.filter(function(el) {
return a.indexOf(el) === -1;
}));
}
【讨论】:
ES2015 版本
Array.prototype.diff = function(a) {return this.filter(i => a.indexOf(i) < 0)};
Array.prototype.union = function(a) {return [...this.diff(a), ...a]}
【讨论】:
如果你想要一个自定义equals函数来匹配你的元素,你可以在ES2015中使用这个函数:
function unionEquals(left, right, equals){
return left.concat(right).reduce( (acc,element) => {
return acc.some(elt => equals(elt, element))? acc : acc.concat(element)
}, []);
}
它遍历左+右数组。然后对于每个元素,如果在累加器中找不到该元素,则将填充累加器。最后,没有equals 函数指定的重复项。
很漂亮,但对于数千个对象可能不是很有效。
【讨论】:
我认为创建一个新数组是最简单的,只添加由 indexOf 确定的唯一值。
在我看来,这似乎是最直接的解决方案,虽然我不知道它是否是最有效的。不保留排序规则。
var a = [34, 35, 45, 48, 49],
b = [48, 55];
var c = union(a, b);
function union(a, b) { // will work for n >= 2 inputs
var newArray = [];
//cycle through input arrays
for (var i = 0, l = arguments.length; i < l; i++) {
//cycle through each input arrays elements
var array = arguments[i];
for (var ii = 0, ll = array.length; ii < ll; ii++) {
var val = array[ii];
//only add elements to the new array if they are unique
if (newArray.indexOf(val) < 0) newArray.push(val);
}
}
return newArray;
}
【讨论】:
[i for( i of new Set(array1.concat(array2)))]
让我为你分解一下
// This is a list by comprehension
// Store each result in an element of the array
[i
// will be placed in the variable "i", for each element of...
for( i of
// ... the Set which is made of...
new Set(
// ...the concatenation of both arrays
array1.concat(array2)
)
)
]
换句话说,它首先连接两者,然后删除重复项(一个集合,根据定义不能有重复项)
但请注意,在这种情况下,元素的顺序并不能保证。
【讨论】: