Có cách nào để trả về sự khác biệt giữa hai mảng trong JavaScript không?
Ví dụ:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
O(a1.length x log(a2.length))
- hiệu suất này có thể có trong JavaScript không?
Có cách nào để trả về sự khác biệt giữa hai mảng trong JavaScript không?
Ví dụ:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
// need ["c", "d"]
O(a1.length x log(a2.length))
- hiệu suất này có thể có trong JavaScript không?
Câu trả lời:
Tôi giả sử bạn đang so sánh một mảng bình thường. Nếu không, bạn cần thay đổi vòng lặp for thành vòng lặp for .. in .
function arr_diff (a1, a2) {
var a = [], diff = [];
for (var i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (var i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (var k in a) {
diff.push(k);
}
return diff;
}
console.log(arr_diff(['a', 'b'], ['a', 'b', 'c', 'd']));
console.log(arr_diff("abcd", "abcde"));
console.log(arr_diff("zxc", "zxc"));
Một giải pháp tốt hơn, nếu bạn không quan tâm đến khả năng tương thích ngược, là sử dụng bộ lọc. Nhưng vẫn còn, giải pháp này hoạt động.
var a1 = ['a', 'b'];
và var a2 = ['a', 'b', 'c', 'd', 'b'];
, nó sẽ trở lại câu trả lời sai , tức là ['c', 'd', 'b']
thay vì ['c', 'd']
.
function diff2(a, b) { var i, la = a.length, lb = b.length, res = []; if (!la) return b; else if (!lb) return a; for (i = 0; i < la; i++) { if (b.indexOf(a[i]) === -1) res.push(a[i]); } for (i = 0; i < lb; i++) { if (a.indexOf(b[i]) === -1) res.push(b[i]); } return res; }
Có một cách tốt hơn bằng ES7:
Ngã tư
let intersection = arr1.filter(x => arr2.includes(x));
Đối với [1,2,3] [2,3]
nó sẽ mang lại [2,3]
. Mặt khác, vì [1,2,3] [2,3,5]
sẽ trả lại điều tương tự.
Sự khác biệt
let difference = arr1.filter(x => !arr2.includes(x));
Đối với [1,2,3] [2,3]
nó sẽ mang lại [1]
. Mặt khác, vì [1,2,3] [2,3,5]
sẽ trả lại điều tương tự.
Đối với một sự khác biệt đối xứng , bạn có thể làm:
let difference = arr1
.filter(x => !arr2.includes(x))
.concat(arr2.filter(x => !arr1.includes(x)));
Bằng cách này, bạn sẽ nhận được một mảng chứa tất cả các phần tử của mảng1 không có trong mảng 2 và ngược lại
Như @Joshaven Potter đã chỉ ra câu trả lời của anh ấy, bạn có thể thêm nó vào Array.prototype để nó có thể được sử dụng như thế này:
Array.prototype.diff = function(arr2) { return this.filter(x => !arr2.includes(x)); }
[1, 2, 3].diff([2, 3])
< 0
thay vì== -1
Array
khác biệt là một cái gọi là set operation
, bởi vì tra cứu tài sản là công việc rất riêng của Set
s, là các đơn đặt hàng có cường độ nhanh hơn sau đó indexOf
/ includes
. Nói một cách đơn giản, giải pháp của bạn rất kém hiệu quả và khá chậm.
Set
, giá trị phải là duy nhất, không?
[1,2,3] [2,3,5]
điều kiện là các con số là duy nhất nhưng nếu bạn đã nói [1,1,2,3] [1,2,3,5]
và mong đợi thì [1]
bạn không thể sử dụng Set
. Tuy nhiên, giải pháp của bạn sẽ không hoạt động: - / Tôi đã kết thúc việc tạo chức năng này bởi vì tôi không thể tìm ra một cách thỏa đáng để thực hiện nó ngắn gọn hơn. Nếu bạn có bất kỳ ý tưởng nào về cách làm điều đó, tôi rất muốn biết!
Array.includes()
tính năng ES7 thay vì ES6? (1) (2) - và để tiếp tục, với ES6 bạn có thể sử dụng , Array.some()
ví dụ: let intersection = aArray.filter(a => bArray.some(b => a === b))
không?
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
////////////////////
// Examples
////////////////////
[1,2,3,4,5,6].diff( [3,4,5] );
// => [1, 2, 6]
["test1", "test2","test3","test4","test5","test6"].diff(["test1","test2","test3","test4"]);
// => ["test5", "test6"]
Lưu ý indexOf và bộ lọc không có sẵn trong tức là trước eg9.
[1,2,3].diff([3,4,5])
nó sẽ trả về [1,2]
thay vì [1,2,4,5]
vậy nó không giải quyết được vấn đề trong câu hỏi ban đầu, một điều cần lưu ý.
Đây là cách dễ nhất để có được chính xác kết quả mà bạn đang tìm kiếm, sử dụng jQuery:
var diff = $(old_array).not(new_array).get();
diff
bây giờ chứa những gì trong old_array
đó không phải là trongnew_array
{a: 1} != {a: 1}
) ( bằng chứng )
.not
với một mảng, jQuery sử dụng tiện ích tích hợp sẵn .grep()
dành riêng cho việc lọc các mảng. Tôi không thể thấy điều này thay đổi.
Phương pháp khác biệt trong Underscore (hoặc thay thế thả xuống của nó, Lo-Dash ) cũng có thể làm điều này:
(R)eturns the values from array that are not present in the other arrays
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
=> [1, 3, 4]
Như với bất kỳ chức năng Underscore nào, bạn cũng có thể sử dụng nó theo kiểu hướng đối tượng hơn:
_([1, 2, 3, 4, 5]).difference([5, 2, 10]);
Có hai điều không thể chấp nhận được đối với "sự khác biệt". Tôi sẽ cho phép bạn chọn cái nào bạn muốn. Nói rằng bạn có:
var a1 = ['a', 'b' ];
var a2 = [ 'b', 'c'];
Nếu bạn muốn lấy ['a']
, sử dụng chức năng này:
function difference(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if (a2.indexOf(a1[i]) === -1) {
result.push(a1[i]);
}
}
return result;
}
Nếu bạn muốn lấy ['a', 'c']
(tất cả các phần tử có trong một a1
hoặc a2
, nhưng không phải cả hai - cái gọi là sự khác biệt đối xứng ), hãy sử dụng hàm này:
function symmetricDifference(a1, a2) {
var result = [];
for (var i = 0; i < a1.length; i++) {
if (a2.indexOf(a1[i]) === -1) {
result.push(a1[i]);
}
}
for (i = 0; i < a2.length; i++) {
if (a1.indexOf(a2[i]) === -1) {
result.push(a2[i]);
}
}
return result;
}
Nếu bạn đang sử dụng lodash, bạn có thể sử dụng _.difference(a1, a2)
(trường hợp 1 ở trên) hoặc_.xor(a1, a2)
(trường hợp 2).
Nếu bạn đang sử dụng Underscore.js, bạn có thể sử dụng _.difference(a1, a2)
hàm cho trường hợp 1.
Các mã trên hoạt động trên tất cả các trình duyệt. Tuy nhiên, đối với các mảng lớn hơn khoảng 10.000 mặt hàng, nó trở nên khá chậm, vì nó có độ phức tạp O (n²). Trên nhiều trình duyệt hiện đại, chúng ta có thể tận dụng Set
đối tượng ES6 để tăng tốc mọi thứ. Lodash tự động sử dụng Set
khi có sẵn. Nếu bạn không sử dụng lodash, hãy sử dụng cách triển khai sau, lấy cảm hứng từ bài đăng trên blog của Axel Rauschmayer :
function difference(a1, a2) {
var a2Set = new Set(a2);
return a1.filter(function(x) { return !a2Set.has(x); });
}
function symmetricDifference(a1, a2) {
return difference(a1, a2).concat(difference(a2, a1));
}
Hành vi cho tất cả các ví dụ có thể gây ngạc nhiên hoặc không rõ ràng nếu bạn quan tâm đến các mảng -0, +0, NaN hoặc thưa thớt. (Đối với hầu hết các mục đích sử dụng, điều này không thành vấn đề.)
Để có được khác biệt đối xứng, bạn cần so sánh các mảng theo cả hai cách (hoặc trong tất cả các cách trong trường hợp có nhiều mảng)
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => !b.includes(x)),
...b.filter(x => !a.includes(x))
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => !unique.includes(x));
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
return [
...a.filter(x => b.indexOf(x) === -1),
...b.filter(x => a.indexOf(x) === -1)
];
}
// diff between multiple arrays:
function arrayDiff(...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter(x => unique.indexOf(x) === -1);
}));
}
// diff between just two arrays:
function arrayDiff(a, b) {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var other = i === 1 ? a : b;
arr.forEach(function(x) {
if (other.indexOf(x) === -1) {
diff.push(x);
}
});
})
return diff;
}
// diff between multiple arrays:
function arrayDiff() {
var arrays = Array.prototype.slice.call(arguments);
var diff = [];
arrays.forEach(function(arr, i) {
var others = arrays.slice(0);
others.splice(i, 1);
var otherValues = Array.prototype.concat.apply([], others);
var unique = otherValues.filter(function (x, j) {
return otherValues.indexOf(x) === j;
});
diff = diff.concat(arr.filter(x => unique.indexOf(x) === -1));
});
return diff;
}
Thí dụ:
// diff between two arrays:
const a = ['a', 'd', 'e'];
const b = ['a', 'b', 'c', 'd'];
arrayDiff(a, b); // (3) ["e", "b", "c"]
// diff between multiple arrays
const a = ['b', 'c', 'd', 'e', 'g'];
const b = ['a', 'b'];
const c = ['a', 'e', 'f'];
arrayDiff(a, b, c); // (4) ["c", "d", "g", "f"]
function arrayDiffByKey(key, ...arrays) {
return [].concat(...arrays.map( (arr, i) => {
const others = arrays.slice(0);
others.splice(i, 1);
const unique = [...new Set([].concat(...others))];
return arr.filter( x =>
!unique.some(y => x[key] === y[key])
);
}));
}
Thí dụ:
const a = [{k:1}, {k:2}, {k:3}];
const b = [{k:1}, {k:4}, {k:5}, {k:6}];
const c = [{k:3}, {k:5}, {k:7}];
arrayDiffByKey('k', a, b, c); // (4) [{k:2}, {k:4}, {k:6}, {k:7}]
Một cách tiếp cận sạch hơn trong ES6 là giải pháp sau đây.
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
a2.filter(d => !a1.includes(d)) // gives ["c", "d"]
a2.filter(d => a1.includes(d)) // gives ["a", "b"]
[ ...a2.filter(d => !a1.includes(d)),
...a1.filter(d => !a2.includes(d)) ]
a1 = ['a', 'b', 'e']
: e sẽ không được trích xuất.
Bạn có thể sử dụng Set trong trường hợp này. Nó được tối ưu hóa cho loại hoạt động này (liên minh, giao lộ, sự khác biệt).
Hãy chắc chắn rằng nó áp dụng cho trường hợp của bạn, một khi nó cho phép không trùng lặp.
var a = new JS.Set([1,2,3,4,5,6,7,8,9]);
var b = new JS.Set([2,4,6,8]);
a.difference(b)
// -> Set{1,3,5,7,9}
Set
chức năng mà không phải lấy mọi thứ khác ...
function diff(a1, a2) {
return a1.concat(a2).filter(function(val, index, arr){
return arr.indexOf(val) === arr.lastIndexOf(val);
});
}
Hợp nhất cả hai mảng, các giá trị duy nhất sẽ chỉ xuất hiện một lần, vì vậy indexOf () sẽ giống như lastIndexOf ().
để trừ một mảng từ mảng khác, chỉ cần sử dụng đoạn mã dưới đây:
var a1 = ['1','2','3','4','6'];
var a2 = ['3','4','5'];
var items = new Array();
items = jQuery.grep(a1,function (item) {
return jQuery.inArray(item, a2) < 0;
});
Nó sẽ trả về ['1,' 2 ',' 6 '] là các mục của mảng thứ nhất không tồn tại trong phần thứ hai.
Do đó, theo mẫu vấn đề của bạn, mã sau đây là giải pháp chính xác:
var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var _array = new Array();
_array = jQuery.grep(array2, function (item) {
return jQuery.inArray(item, array1) < 0;
});
Với sự xuất hiện của ES6 với các bộ và toán tử splat (tại thời điểm chỉ hoạt động trong Firefox, hãy kiểm tra bảng tương thích ), bạn có thể viết một lớp lót sau:
var a = ['a', 'b', 'c', 'd'];
var b = ['a', 'b'];
var b1 = new Set(b);
var difference = [...new Set([...a].filter(x => !b1.has(x)))];
Điều đó sẽ dẫn đến [ "c", "d" ]
.
b.filter(x => !a.indexOf(x)))
O(n + m)
của bạn là O(n * m)
trong đó n và m là độ dài của mảng. Lấy danh sách dài và giải pháp của tôi sẽ chạy trong vài giây, trong khi của bạn sẽ mất hàng giờ.
a.filter(x => !b1.has(x))
đơn giản hơn Và lưu ý spec chỉ đòi hỏi sự phức tạp là n * f(m) + m
với f(m)
sublinear trên trung bình. Nó tốt hơn n * m
, nhưng không nhất thiết n + m
.
var difference = [...new Set([...a].filter(x => !b1.has(x)))];
Tại sao bạn tạo bản sao 'a'? Tại sao bạn biến kết quả của bộ lọc thành một tập hợp và sau đó trở lại thành mảng? Điều này không tương đương vớivar difference = a.filter(x => !b1.has(x));
Tính toán difference
giữa hai mảng là một trong các Set
hoạt động. Thuật ngữ đã chỉ ra rằng Set
loại bản địa nên được sử dụng, để tăng tốc độ tra cứu. Dù sao, có ba hoán vị khi bạn tính toán sự khác biệt giữa hai bộ:
[+left difference] [-intersection] [-right difference]
[-left difference] [-intersection] [+right difference]
[+left difference] [-intersection] [+right difference]
Đây là một giải pháp chức năng phản ánh những hoán vị này.
difference
:// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// left difference
const differencel = xs => ys => {
const zs = createSet(ys);
return filter(x => zs.has(x)
? false
: true
) (xs);
};
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
// run the computation
console.log( differencel(xs) (ys) );
difference
:differencer
là tầm thường. Nó chỉ là differencel
với các đối số lật. Bạn có thể viết một hàm cho thuận tiện:const differencer = flip(differencel)
. Đó là tất cả!
difference
:Bây giờ chúng ta có bên trái và bên phải, việc thực hiện đối xứng cũng difference
trở nên tầm thường:
// small, reusable auxiliary functions
const apply = f => x => f(x);
const flip = f => y => x => f(x) (y);
const concat = y => xs => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// left difference
const differencel = xs => ys => {
const zs = createSet(ys);
return filter(x => zs.has(x)
? false
: true
) (xs);
};
// symmetric difference
const difference = ys => xs =>
concat(differencel(xs) (ys)) (flip(differencel) (xs) (ys));
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,3,6,7,8,9];
// run the computation
console.log( difference(xs) (ys) );
Tôi đoán ví dụ này là một điểm khởi đầu tốt để có được ấn tượng về ý nghĩa của lập trình chức năng:
Lập trình với các khối xây dựng có thể được cắm với nhau theo nhiều cách khác nhau.
Một giải pháp sử dụng indexOf()
sẽ ổn đối với các mảng nhỏ nhưng khi chúng phát triển theo chiều dài thì hiệu suất của các phương pháp tiếp cận thuật toán O(n^2)
. Đây là một giải pháp sẽ hoạt động tốt hơn cho các mảng rất lớn bằng cách sử dụng các đối tượng làm mảng kết hợp để lưu trữ các mục mảng dưới dạng các khóa; nó cũng tự động loại bỏ các mục trùng lặp nhưng chỉ hoạt động với các giá trị chuỗi (hoặc các giá trị có thể được lưu trữ an toàn dưới dạng chuỗi):
function arrayDiff(a1, a2) {
var o1={}, o2={}, diff=[], i, len, k;
for (i=0, len=a1.length; i<len; i++) { o1[a1[i]] = true; }
for (i=0, len=a2.length; i<len; i++) { o2[a2[i]] = true; }
for (k in o1) { if (!(k in o2)) { diff.push(k); } }
for (k in o2) { if (!(k in o1)) { diff.push(k); } }
return diff;
}
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
arrayDiff(a1, a2); // => ['c', 'd']
arrayDiff(a2, a1); // => ['c', 'd']
Câu trả lời trên của Joshaven Potter là tuyệt vời. Nhưng nó trả về các phần tử trong mảng B không nằm trong mảng C, nhưng không phải là cách khác. Ví dụ: nếu var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
sau đó nó sẽ xuất ra: ==> [1,2,6]
, nhưng không [1,2,6,7]
, đó là sự khác biệt thực tế giữa hai. Bạn vẫn có thể sử dụng mã của Potter ở trên nhưng chỉ cần làm lại so sánh một lần nữa:
Array.prototype.diff = function(a) {
return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};
////////////////////
// Examples
////////////////////
var a=[1,2,3,4,5,6].diff( [3,4,5,7]);
var b=[3,4,5,7].diff([1,2,3,4,5,6]);
var c=a.concat(b);
console.log(c);
Điều này sẽ xuất ra: [ 1, 2, 6, 7 ]
Một cách khác để giải quyết vấn đề
function diffArray(arr1, arr2) {
return arr1.concat(arr2).filter(function (val) {
if (!(arr1.includes(val) && arr2.includes(val)))
return val;
});
}
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]); // return [7, 4, 5]
Ngoài ra, bạn có thể sử dụng cú pháp hàm mũi tên:
const diffArray = (arr1, arr2) => arr1.concat(arr2)
.filter(val => !(arr1.includes(val) && arr2.includes(val)));
diffArray([1, 2, 3, 7], [3, 2, 1, 4, 5]); // return [7, 4, 5]
Array.prototype.difference = function(e) {
return this.filter(function(i) {return e.indexOf(i) < 0;});
};
eg:-
[1,2,3,4,5,6,7].difference( [3,4,5] );
=> [1, 2, 6 , 7]
difference
là hàm trong phiên bản tương lai và chức năng này có chữ ký hàm khác thì bạn sẽ phá vỡ mã của bạn hoặc các thư viện nước ngoài sử dụng chức năng này.
Giải pháp rất đơn giản với chức năng lọc của JavaScript:
var a1 = ['a', 'b'];
var a2 = ['a', 'b', 'c', 'd'];
function diffArray(arr1, arr2) {
var newArr = [];
var myArr = arr1.concat(arr2);
newArr = myArr.filter(function(item){
return arr2.indexOf(item) < 0 || arr1.indexOf(item) < 0;
});
alert(newArr);
}
diffArray(a1, a2);
Còn cái này thì sao:
Array.prototype.contains = function(needle){
for (var i=0; i<this.length; i++)
if (this[i] == needle) return true;
return false;
}
Array.prototype.diff = function(compare) {
return this.filter(function(elem) {return !compare.contains(elem);})
}
var a = new Array(1,4,7, 9);
var b = new Array(4, 8, 7);
alert(a.diff(b));
Vì vậy, theo cách này bạn có thể làm array1.diff(array2)
để có được sự khác biệt của chúng (Độ phức tạp thời gian khủng khiếp cho thuật toán mặc dù - O (mảng1.length x mảng2.length) Tôi tin)
Sử dụng http://phrogz.net/JS/ArraySetMath.js bạn có thể:
var array1 = ["test1", "test2","test3", "test4"];
var array2 = ["test1", "test2","test3","test4", "test5", "test6"];
var array3 = array2.subtract( array1 );
// ["test5", "test6"]
var array4 = array1.exclusion( array2 );
// ["test5", "test6"]
filter
)fn
Tham số gọi lại tùy chọn cho phép bạn chỉ định cách so sánh các mục mảngfunction diff(a, b, fn){
var max = Math.max(a.length, b.length);
d = [];
fn = typeof fn === 'function' ? fn : false
for(var i=0; i < max; i++){
var ac = i < a.length ? a[i] : undefined
bc = i < b.length ? b[i] : undefined;
for(var k=0; k < max; k++){
ac = ac === undefined || (k < b.length && (fn ? fn(ac, b[k]) : ac == b[k])) ? undefined : ac;
bc = bc === undefined || (k < a.length && (fn ? fn(bc, a[k]) : bc == a[k])) ? undefined : bc;
if(ac == undefined && bc == undefined) break;
}
ac !== undefined && d.push(ac);
bc !== undefined && d.push(bc);
}
return d;
}
alert(
"Test 1: " +
diff(
[1, 2, 3, 4],
[1, 4, 5, 6, 7]
).join(', ') +
"\nTest 2: " +
diff(
[{id:'a',toString:function(){return this.id}},{id:'b',toString:function(){return this.id}},{id:'c',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
[{id:'a',toString:function(){return this.id}},{id:'e',toString:function(){return this.id}},{id:'f',toString:function(){return this.id}},{id:'d',toString:function(){return this.id}}],
function(a, b){ return a.id == b.id; }
).join(', ')
);
length
giá trị. Đó là tài sản đơn giản. jsperf.com/array-length-caching
Điều này đang hoạt động: về cơ bản hợp nhất hai mảng, tìm kiếm các bản sao và đẩy những gì không trùng lặp thành một mảng mới, đó là sự khác biệt.
function diff(arr1, arr2) {
var newArr = [];
var arr = arr1.concat(arr2);
for (var i in arr){
var f = arr[i];
var t = 0;
for (j=0; j<arr.length; j++){
if(arr[j] === f){
t++;
}
}
if (t === 1){
newArr.push(f);
}
}
return newArr;
}
còn một câu trả lời khác, nhưng dường như không ai đề cập đến jsperf khi họ so sánh một số thuật toán và hỗ trợ công nghệ: https://jsperf.com/array-difference-javascript dường như sử dụng bộ lọc có kết quả tốt nhất. cảm ơn
Chỉ cần suy nghĩ ... vì lợi ích của một thách thức ;-) điều này sẽ hoạt động ... (đối với các mảng cơ bản của chuỗi, số, v.v.) không có mảng lồng nhau
function diffArrays(arr1, arr2, returnUnion){
var ret = [];
var test = {};
var bigArray, smallArray, key;
if(arr1.length >= arr2.length){
bigArray = arr1;
smallArray = arr2;
} else {
bigArray = arr2;
smallArray = arr1;
}
for(var i=0;i<bigArray.length;i++){
key = bigArray[i];
test[key] = true;
}
if(!returnUnion){
//diffing
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = null;
}
}
} else {
//union
for(var i=0;i<smallArray.length;i++){
key = smallArray[i];
if(!test[key]){
test[key] = true;
}
}
}
for(var i in test){
ret.push(i);
}
return ret;
}
array1 = "test1", "test2","test3", "test4", "test7"
array2 = "test1", "test2","test3","test4", "test5", "test6"
diffArray = diffArrays(array1, array2);
//returns ["test5","test6","test7"]
diffArray = diffArrays(array1, array2, true);
//returns ["test1", "test2","test3","test4", "test5", "test6","test7"]
Lưu ý việc sắp xếp có thể sẽ không được như đã lưu ý ở trên ... nhưng nếu muốn, hãy gọi .sort () trên mảng để sắp xếp nó.
Tôi muốn một hàm tương tự có một mảng cũ và một mảng mới và đưa cho tôi một mảng các mục được thêm vào và một mảng các mục bị loại bỏ, và tôi muốn nó có hiệu quả (vì vậy không có .contains!).
Bạn có thể chơi với giải pháp đề xuất của tôi ở đây: http://jsbin.com/osewu3/12 .
Bất cứ ai cũng có thể thấy bất kỳ vấn đề / cải tiến cho thuật toán đó? Cảm ơn!
Mã danh sách:
function diff(o, n) {
// deal with empty lists
if (o == undefined) o = [];
if (n == undefined) n = [];
// sort both arrays (or this won't work)
o.sort(); n.sort();
// don't compare if either list is empty
if (o.length == 0 || n.length == 0) return {added: n, removed: o};
// declare temporary variables
var op = 0; var np = 0;
var a = []; var r = [];
// compare arrays and add to add or remove lists
while (op < o.length && np < n.length) {
if (o[op] < n[np]) {
// push to diff?
r.push(o[op]);
op++;
}
else if (o[op] > n[np]) {
// push to diff?
a.push(n[np]);
np++;
}
else {
op++;np++;
}
}
// add remaining items
if( np < n.length )
a = a.concat(n.slice(np, n.length));
if( op < o.length )
r = r.concat(o.slice(op, o.length));
return {added: a, removed: r};
}
Tôi đang tìm kiếm một câu trả lời đơn giản không liên quan đến việc sử dụng các thư viện khác nhau và tôi đã đưa ra câu trả lời của riêng mình mà tôi không nghĩ đã được đề cập ở đây. Tôi không biết nó hiệu quả như thế nào hoặc bất cứ điều gì nhưng nó hoạt động;
function find_diff(arr1, arr2) {
diff = [];
joined = arr1.concat(arr2);
for( i = 0; i <= joined.length; i++ ) {
current = joined[i];
if( joined.indexOf(current) == joined.lastIndexOf(current) ) {
diff.push(current);
}
}
return diff;
}
Đối với mã của tôi, tôi cũng cần các bản sao được lấy ra, nhưng tôi đoán rằng không phải lúc nào cũng được ưa thích.
Tôi đoán nhược điểm chính là nó có khả năng so sánh nhiều lựa chọn đã bị từ chối.
sửa chữa bitcoin cho câu trả lời tốt nhất
function arr_diff(a1, a2)
{
var a=[], diff=[];
for(var i=0;i<a1.length;i++)
a[a1[i]]=a1[i];
for(var i=0;i<a2.length;i++)
if(a[a2[i]]) delete a[a2[i]];
else a[a2[i]]=a2[i];
for(var k in a)
diff.push(a[k]);
return diff;
}
điều này sẽ xem xét loại yếu tố hiện tại. b / c khi chúng tôi tạo [a1 [i]], nó chuyển đổi một giá trị thành chuỗi từ giá trị gốc của nó, vì vậy chúng tôi đã mất giá trị thực tế.