Determine deleted, added and added between two arrays

I am trying to find deep differences between two arrays like below

 var arr = [5,4,6,7,8,9]; var against = [1,2,4,5,6];

      

then the result should be

 appended = [7, 8, 9], prepended = [], removed = [1, 2]

      

I'm running out of logic and this is what I tried

 var prepend = [];
 var append = [];
 var removed = [];

 var len = against.length;

 while (len--) {
    var itm = listSplit[len];
    if (arr.indexOf(itm) === -1) {
       removed.push(len);
    } else if (itm < arr[0]) {
       // ??
    }
 }

      

How to find these values. Give me some insight into the logic to find this .

+3


source to share


6 answers


One solution might be:

var arr = [7,8,9,5,4,6]; 
var against = [1,2,4,5,6];
// make a copy of the original array as appended
var appended = arr;
var removed =[];
var prepended =[];

for(var i=0;i<against.length;i++)
{  
    //if the element is not present in the original array, add it to removed.
    if(appended.indexOf(against[i]) == -1)
    {
        removed.push(against[i]);
    }
    else
    {
        //if it is already present, it was not appended, nor prepended, 
        //remove it from appended.
        appended.splice(appended.indexOf(against[i]),1);
    }
}
// one more loop to seperate the prepended from the appended values.
for(var j=0;j<appended.length;j++)
{   
    if(appended[j] < against[against.length-1])
    {
        prepended.push(appended.splice(j,1));
        j--;
    }
}

      



The final values ​​in the added array will be added, and the deleted ones will be deleted. The saved ones will be added.

+2


source


Unhappy answer: it's impossible.

This is not possible because we do not have a "changelog" of what happened to the array to get it in a specific state.

Consider, for example, the following arrays:

var original = [2, 2, 2];

var modified1 = original.concat(2);

var modified2 = [2].concat(original);

var modified3 = modified2.slice(1);

      

This is of course an extreme example, but in their final states it modified1

has the same content as modified2

(despite the fact that it has different paths to get there), and, perhaps worse, modified3

actually has the same meaning original

, despite the fact , which at the same time was significantly changed.

Conclusion: Without very strict rules about what modifications can be made to arrays and in what order, it is impossible to be as specific as saying what has been added, added or removed.

However, you can always make a difference. Diffs are useful in this case because they don't care how the changes happened; they only care about what the final difference really is. However, keep in mind that you still need to define how you want diff to work. That is, given the following arrays:

var array1 = [1, 2, 3, 4, 5];

var array = [2, 3, 4, 5, 6];

      



... would you define it as two changes?

  • Removed presenter 1

  • Added trailing 6

... or five changes (since the values ​​are different for each index)? If you only say two, then how about:

var array1 = [1, 1];

var array = [1, 6];

      

It's the same change (remove the leading 1

, add the final 6

), but in this case it looks more like one change:

  • Change trailing 1

    to 6

    .

So yes, this is one of the "answer a question by answering a bunch of other questions" answer, but you need to be clear about what you need here. Be that as it may, to account for more than a few ambiguous cases.

+2


source


My answer is quite complex, but it gets the job done.

JSFIDDLE

var arr = [5,4,6,7,8,9,3];
var against = [1,2,4,5,6];
var prepend = [];
var append = [];
var removed = [];
for(i=0;i<arr.length;i++){
    for(j=0;j<against.length;j++){
        if(arr[i]==against[j])
            break;
        else if(j==against.length)
            append.push(arr[i]);
        else if((parseInt(against.toString().replace(/,/g,"").indexOf(arr[i]))!=-1)!=true
               && arr[i]<against[against.length-1]
               && (parseInt(prepend.toString().replace(/,/g,"").indexOf(arr[i]))!=-1)!=true)
            prepend.push(arr[i]);
        else if(parseInt(removed.toString().replace(/,/g,"").indexOf(against[j]))==-1
               && (parseInt(arr.toString().replace(/,/g,"").indexOf(against[j]))!=-1)!=true)
            removed.push(against[j]);
        else if(parseInt(against.toString().replace(/,/g,"").indexOf(arr[i]))==-1
               && (parseInt(append.toString().replace(/,/g,"").indexOf(arr[i]))!=-1)!=true
               && (parseInt(prepend.toString().replace(/,/g,"").indexOf(arr[i]))!=-1)!=true)
            append.push(arr[i]);   
    }
}
//testing
    console.log("Appended = [" + append.toString() + "]");
    console.log("Prepended = [" + prepend.toString() + "]");
    console.log("Removed = [" + removed.toString() + "]");

      

+1


source


Updated script

Not sure if you want the result in VanillaJS or with another library. With Underscore.JS or Lodash.JS, you would do something like:

_.difference(against, arr) // [1,2] aka removed
_.difference(arr, against) // [7,8,9] aka appended

      

I don't understand what you mean with the appendix because your example does not contain this information. Was it the difference between the added numbers that are added before / after the original arr? How about the gaps you need to fill? Perhaps you can think of some additional examples.

In the case of a simple pre / app nding, you will search for the lowest number against and split the append () result by this one. All before = preend, then = append. This can be accomplished with the following approach:

// Lets say the difference is [1,7,8,9] and min number of against = 2
_.filter(_.difference(arr, against), function(n) { return n < _.min(against) }) // [1]
_.filter(_.difference(arr, against), function(n) { return n > _.min(against) }) // [7,8,9]

      

+1


source


It works.

// 1. inputs are sorted arrays. example [ -7, -6, 0, 4, 5, 6, 7, 8, 9 ] [ 1, 2, 4, 5, 6 ]
// 2. differences are contiguous. If not, question the question!
function diff(now, was) {
var results = {prepended:[], appended:[], removed:[]}
    // prepended is -7 thru 0. Its realm is the now array
    for ( var inow = 0; inow < now.length; ++inow ) {
        if ( now[inow] >= was[0] ) {
            break;
        }
    }
    // inow points to first element in now that is part of was
    results.prepended = now.slice(0,inow);

    // removed is 1 thru 2. Its realm is the was array
    var ref = now[inow];
    for ( var iwas = 0; iwas < was.length; ++iwas ) {
        if ( was[iwas] == ref ) {
            break;
        }
    }
    // iwas points to the first element in was that is present in now
    results.removed = was.slice(0,iwas);

    // appended is 7 thru 9. Its realm is now
    var ref = was[was.length-1];
    var i = now.indexOf(ref);
    if ( i !== -1 ) {
        while ( ++i < now.length && now[i] == ref ) {}
        results.appended = now.slice(i);
    }
    console.log("> orig", now, was);
    console.log("> results", results);
}

console.log("\nempties");
diff([], []);

console.log("\nsample");
diff([-7,-6,0,4,5,6,7,8,9], [1,2,4,5,6]);

console.log("\nsample2");
diff([-7,-6,0,4,5,6,6,7,8,9], [1,2,4,5,6]);

console.log("\nonly prepended/removed");
diff([-7,-6,0,4,5,6], [1,2,4,5,6]);

console.log("\nonly removed");
diff([4,5,6], [1,2,2,4,4,5,6]);

      

Exit on startup in node

C:\node>node pa.js

empties
> orig [] []
> results { prepended: [], appended: [], removed: [] }

sample
> orig [ -7, -6, 0, 4, 5, 6, 7, 8, 9 ] [ 1, 2, 4, 5, 6 ]
> results { prepended: [ -7, -6, 0 ],
  appended: [ 7, 8, 9 ],
  removed: [ 1, 2 ] }

sample2
> orig [ -7, -6, 0, 4, 5, 6, 6, 7, 8, 9 ] [ 1, 2, 4, 5, 6 ]
> results { prepended: [ -7, -6, 0 ],
  appended: [ 7, 8, 9 ],
  removed: [ 1, 2 ] }

only prepended/removed
> orig [ -7, -6, 0, 4, 5, 6 ] [ 1, 2, 4, 5, 6 ]
> results { prepended: [ -7, -6, 0 ], appended: [], removed: [ 1, 2 ] }

only removed
> orig [ 4, 5, 6 ] [ 1, 2, 2, 4, 4, 5, 6 ]
> results { prepended: [], appended: [], removed: [ 1, 2, 2 ] }

      

+1


source


You can only get the answer using the filter function.

That's what you want

var appended = arr.filter(function (elm) {
    return against.filter(function (elm2) {
        return elm2 == elm
    }).length == 0;
})

      

The above code is for the added array.

var removed = against.filter(function (elm) {
    return elm < arr[0]
});

      

Above code for remote array

var prepended = arr.filter(function (elm) {
    return elm < against[0]
});

      

The above code is for a pre-array.

0


source







All Articles