[英]Taking the difference of two arrays and making a new array
我需要这个函数来比较两个数组并返回一个新数组,该数组只包含两个数组都不常见的元素。 我写了以下代码:
function diff(arr1, arr2) {
var newArray = [];
for (var i=0;i<arr1.length;i++){
for (var j=0;j<arr2.length;j++){
if (arr1[i]===arr2[j]){
arr1.splice(i,1);
arr2.splice(j,1);
}
}
}
newArray = arr1.concat(arr2);
return newArray;
}
diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
但它返回[2,2,4]而不仅仅[4]
另外,我尝试使用filter方法编写它:
function diff(arr1, arr2) {
var newArray = [];
function compare(x){
for (var i = 0;i<arr2.length;i++){
return x != arr2[i];
}
}
newArray = arr1.filter(compare);
return newArray;
}
diff([1, 2, 3, 5], [1, 2, 3, 4, 5]);
这对每个实例都不起作用。 我需要能够将数组与数字和字符串进行比较。 它必须是javascript,没有jquery为此。
你可以试试:
function diff(arr1, arr2) {
var tmp = [];
var newArray = [];
for (var i = 0; i < arr1.length; i++) {
for (var j = 0; j < arr2.length; j++) {
if (arr1[i] === arr2[j]) {
arr1[i] = arr2[j] = null;
}
}
}
tmp = arr1.concat(arr2);
for (var i = 0; i < tmp.length; i++) {
if (tmp[i] !==null) {
newArray.push(tmp[i]);
}
}
return newArray;
}
console.log(diff([0,1,2], [1,2]));//output: [0]
当您splice
数组时,所有元素都会向下移动,这会使您的循环跳跃一步。 例如,当它删除1
“在S 0th
位置2
的移动到新的0th
您已经检查它旁边跳过一部分。 解决这个问题的一个简单方法就是当你拼接时确保你退步,你可以减少i
和j
:
if (arr1[i]===arr2[j]) {
arr1.splice(i,1);
arr2.splice(j,1);
i--;
j--;
}
.splice
改变数组,所以它与你的循环混乱。 对代码的一个简单修复就是以相反的顺序迭代:
for (var i=arr1.length; i--;){
for (var j=arr2.length; j--){
}
}
然而,这仍然存在你经常拼接arr1
的问题。 arr1
应该每次迭代只拼接一次:
for (var i=arr1.length; i--;){
var same = false;
for (var j=arr2.length; j--;){
if (arr1[i] === arr2[j]) {
same = true;
arr2.splice(j, 1);
break;
}
}
if (same) {
arr1.splice(i, 1);
}
}
function diff(arr1, arr2) { for (var i = arr1.length; i--;) { var same = false; for (var j = arr2.length; j--;) { if (arr1[i] === arr2[j]) { same = true; arr2.splice(j, 1); break; } } if (same) { arr1.splice(i, 1); } } return arr1.concat(arr2); } console.log(diff([1, 2, 3, 5], [1, 2, 3, 4, 5]));
对两个数组进行排序,从中删除重复项,连接两个数组,对获取的数组进行排序,并从获取的数组中删除重复项。
function getArraysDifference(a1, a2) {
sortAndRemoveDuplicates(a1);
sortAndRemoveDuplicates(a2);
var outputArray = a1.concat(a2)
sortAndRemoveDuplicates(outputArray);
return outputArray;
}
function sortAndRemoveDuplicates(inputArray) {
inputArray.sort();
var lastValue = inputArray[0];
var i = 0;
var currentValue;
for (i = 1; i < inputArray.length; i++) {
currentValue = inputArray[i];
if (currentValue === lastValue) {
inputArray.splice(i, 1);
i--;
} else {
lastValue = currentValue;
}
}
}
O((N + M)log(N + M))的最坏情况时间复杂度 。 您尝试的解决方案有效但时间复杂度为O(N * M)。
事实证明,由于webkit(我没有在其他浏览器上进行调查)使用选择排序进行排序,因此该解决方案会导致时间复杂度O(NM)。 在Java中,这种方法应该更快,因为引擎甚至可以达到O(N)来排序合理的短数组,否则会降低O(N log(N))复杂度以进行排序。
设置临时对象。 迭代两个数组。 对于每个数组中的每个元素,如果该元素不是临时对象中的键,则将该对象中的键设置为等于该值为true
元素。 如果已访问过某个元素,请将其删除。
最后,返回Object.keys(obj)以获取键的数组。
function differenceOfTwoArrays(arr1, arr2) {
var obj = {};
arr1.forEach(function(elem) {
if (!obj[elem]) {
obj[elem] = true;
} else if (obj[elem]) {
delete (obj[elem]);
}
});
arr2.forEach(function(elem) {
if(!obj[elem]) {
obj[elem] = true;
} else if (obj[elem]) {
delete (obj[elem]);
}
});
return Object.keys(obj);
}
代码少于其他答案:
function diff(arr1, arr2) {
var newArray = [];
for (var i=0;i<arr1.length;i++) {
if (arr2.indexOf(arr1[i]) == -1) newArray.push(arr1[i]);
}
for (var i=0;i<arr2.length;i++){
if (arr1.indexOf(arr2[i]) == -1) newArray.push(arr2[i]);
}
return newArray;
}
编辑 :比较一些答案: https : //jsfiddle.net/c42wvvr5/2/
似乎这个答案在Chrome上是最快的,而且比在Firefox上的杨稍慢。
将数组值转换为对象键可以使其更快:
function diff_dms2(arr1, arr2) {
var newArray = [];
var ob1 = { };
var ob2 = { };
for (var i=0; i<arr1.length; i++) ob1[arr1[i]] = true;
for (var i=0; i<arr2.length; i++) ob2[arr2[i]] = true;
for (var i=0;i<arr1.length;i++) {
if (!ob2[arr1[i]]) newArray.push(arr1[i]);
}
for (var i=0;i<arr2.length;i++){
if (!ob1[arr2[i]]) newArray.push(arr2[i]);
}
return newArray;
}
除非你有真正庞大的数组,否则我会选择代码更简单的那个。
这是一个有趣的“参考”实现。 它的目的不是特别快速或有效,而是要正确并从代码中阐明算法,这有助于确保正确性。 您可以编写“更好”的版本,并将它们与此版本进行比较,以确保正确性。 “自动化测试是最好的测试。” :-)
它确实完成了问题中所述:元素 - 不一定是整数 - 两个数组共有的数据都从两个数组中删除。 这意味着一个数组中的重复项目在另一个数组中找不到,保持不变。
function arrayDiff( array1, array2 ) { var r1 = array1.slice(); var r2 = array2.slice(); var r1Unique = []; // collector for known "unique" values while( !r1.every( function( r1Obj ) { var uniqueR1Obj = r2.every( function( r2Obj ) { if( r1Obj !== r2Obj ) { return true; // unique so far, keep processing } // collision: remove all references to this object in R2 var newR2 = []; r2.forEach( function( oldR2Obj ) { if( oldR2Obj !== r2Obj ) { newR2.push( oldR2Obj ); } } ); r2 = newR2; // start operating on the new smaller array return false; // uniqueness lost, bail } ); if( uniqueR1Obj ) { r1Unique.push( r1Obj ); } // remove all references to this object in R1 var newR1 = []; r1.forEach( function( oldR1Obj ) { if( oldR1Obj !== r1Obj ) { newR1.push( oldR1Obj ); } } ); r1 = newR1; // start operating on the new smaller array return uniqueR1Obj; // keep processing if still unique, or bail } ) ); return r1Unique.concat( r1.concat( r2 ) ); } function addTestResults( r1, r2 ) { var s = 'arrayDiff( [ ' + r1 + ' ], [ ' + r2 + ' ] ) == [ ' + arrayDiff( r1, r2 ) + ' ]<br/>'; el = document.getElementById( "output" ); if( el !== null ) el.innerHTML += s; } var testArray1 = [ 1, 2, 4, 8, 16, 32, 0 ]; var testArray2 = [ 1, 1, 3, 8, 15 ]; var testArray3 = [ 32, 3, 8, 0, 8, 8, 15 ]; addTestResults( testArray1, testArray2 ); addTestResults( testArray2, testArray3 ); addTestResults( testArray1, testArray3 );
<pre id="output"></pre>
那一点HTML只是作为“输出设备”。 我不是代码片段的专家。
这是另一种看待它的方式: http : //jsfiddle.net/Lp1zveba/
附录:我还不能评论其他答案,但我喜欢 ' rkho '中的答案 ; 这是它和我的提交的比较: http : //jsfiddle.net/uuh7afLc/
它显示了一些差异,我将对这个问题进行不同的解释; 我完全认为,如果一个元素在两个数组之间是通用的,那么它(及其所有类型)将不会出现在结果数组中。 其他一些答案使用替代解释,即对于每对相似的对象,从每个源阵列中移除一个,并且任一阵列中的任何不匹配的剩余物都可以在到达结果数组的过程中存活。
我们鼓励Asker澄清规范。 :-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.