mightymax
mightymax

Reputation: 431

Javascript compare two arrays and get values that do not match

I really appreciate all your help on this.

I have two arrays:

I need to output a third array, in this case FinalArray that contains a list of all the ArrayFileNameWExt that are not in the ArrayFileName array.

I know I had a thread on finding matched items, which was great. But I'm having problems finding the unmatched items. I changed the == comparison to !== and that gave me one file name a hundred times.

Thank you for your help on this, Maxine

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];
var FinalArray = [];

for (var i = 0; i < ArrayFileName.length; i++) {
    for (var j = 0; j < ArrayFileNameWExt.length; j++) {
        var temp = ArrayFileNameWExt[j].split(".");
        if(ArrayFileName[i]!==temp[0]){
            FinalArray.push(ArrayFileNameWExt[j]);
            break;
        }
    }
}

Upvotes: 2

Views: 21629

Answers (5)

Mulan
Mulan

Reputation: 135227

I would use .filter and .includes -

const fileNames =
  ['one', 'two', 'three', 'three', 'five', 'six', 'ten']

const fileNamesWExt =
  [ 'one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm' ]

const basename = filename =>
  filename.split(/\.[^.]+$/)[0]

const finalArray =
  fileNamesWExt.filter(f => ! fileNames.includes(basename(f)))
  
console.log(finalArray)
// [ 'eleven.cgm' ]

Note our implementation of basename, which is careful to only remove the last extension -

const basename = filename =>
  filename.split(/\.[^.]+$/)[0]
  
console.log
  ( basename ("cat")               // "cat"
  , basename ("cat.dog")           // "cat"
  , basename ("cat.dog.eel")       // "cat.dog"
  , basename ("cat.dog.eel.fox")   // "cat.dog.eel"
  )

If you cannot use arrow functions, you are probably using a pretty old version of JavaScript. In this case, you'll also need to polyfill .includes -

Array.prototype.includes = function (x, init) {
  for (var i = init || 0; i < this.length; i = i + 1)
    if (this[i] === x)
      return true;
  return false;
};

var fileNames =
  ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];

var fileNamesWExt =
  [ 'one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm' ];

var basename = function (filename) {
  return filename.split(/\.[^.]+$/)[0];
};

var finalArray =
  fileNamesWExt.filter(function (f) {
    return ! fileNames.includes(basename(f));
  });
  
console.log(finalArray);
// [ 'eleven.cgm' ]

Upvotes: 2

Serene Abraham Mathew
Serene Abraham Mathew

Reputation: 388

Perhaps Editor would like this

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];
var FinalArray = [];

for (var i = 0; i < ArrayFileNameWExt.length; i++) {

    var matchFound = false;
    for (var j = 0; j < ArrayFileName.length; j++) {
    
        var temp = ArrayFileNameWExt[i].split(".");
        
        if(ArrayFileName[j]==temp[0]){
            matchFound = true;
            break;
        }
    }
    if(!matchFound){
      FinalArray.push(ArrayFileNameWExt[i])
    
    }
    
}

console.log(FinalArray)

Upvotes: 1

Adrian Pop
Adrian Pop

Reputation: 1967

Reusing the code you gave us, I made this: I interchanged the two for-loops and I used a variable (found) to keep track of the found items. Iterating through ArrayFileNameWExt in the outer loop is also better because we lower the number of calls to the split function.

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];
var FinalArray = [];

for (var i = 0; i < ArrayFileNameWExt.length; ++i) {
    var temp = ArrayFileNameWExt[i].split(".");
    var found = false;
    
    for (var j = 0; j < ArrayFileName.length; ++j) {
        if (ArrayFileName[j] === temp[0]) {
            found = true;
            break;
        }
    }
    
    if (!found) {
        FinalArray.push(ArrayFileNameWExt[i]);
    }
}

console.log(FinalArray);

Cheers!

Upvotes: 2

Nick
Nick

Reputation: 16576

You could use a simple filter and return all the items for which the first part of the split is not in the ArrayFileName array.

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];

var final = ArrayFileNameWExt.filter(function(item) {
  return !ArrayFileName.includes(item.split('.')[0]);
})

console.log(final);

If you're using a pretty old version of javascript, the includes Array method might not exist. The following code could be used instead.

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];

var final = ArrayFileNameWExt.filter(function(item) {
  var name = item.split('.')[0];
  for (var i = 0; i < ArrayFileName.length; i++) {
    if (ArrayFileName[i] === name) return false;
  }
  return true;
})

console.log(final);

Upvotes: 4

dquijada
dquijada

Reputation: 1699

Array#filter lets you include (or delete) the elements that meet certain condition.

Array#inludes returns if certain element is included in the array.

String#split returns an array with the elements from splitting the string using the separator that you want (in this case, the point).

var ArrayFileName = ['one', 'two', 'three', 'three', 'five', 'six', 'ten'];
var ArrayFileNameWExt = ['one.txt', 'two.txt', 'three.txt', 'ten.wmf', 'eleven.cgm'];
var FinalArray = [];

FinalArray = ArrayFileNameWExt.filter (filenameWExt => !ArrayFileName.includes(filenameWExt.split('.')[0]));

console.log(FinalArray);

Any further question let me know in the comments and I'll explain

Upvotes: 1

Related Questions