1

I am new to javascript. Now, I want to make comparison of two website pair by iterating two string array as a pair the same time. These two string array's length are the same. I have searched for sites but didn't find the way to do in javascript. For example, in python, people can do this by using zip(), referencing from How to merge lists into a list of tuples?.

However, in javascript, I try to something similar to that, but it will iterate over the second list every time it iterate over the element of first list, which is not want I wanted.

codes not what I expected

var FistList=['https://test1-1/travel','https://test1-1/cook','https://test1-1/eat'];
var SecondList=['https://test1-2/travel','https://test1-2/cook','https://test1-2/eat'];

 FirstList.forEach(firstListItem => {
            SecondList.forEach(secondListItem => {
                //do comparison for these two websites....
            });
        });

What I expect is to do comparison pair by pair, which is =>

first loop: do comparison of 'https://test1-1/travel' and 'https://test1-2/travel'
second loop: do comparison of 'https://test1-1/cook' and 'https://test1-2/cook'
third loop: do comparison of 'https://test1-1/eat' and 'https://test1-2/eat'

I searched for a whole day but cannot find the way to do in javascript. Please advise. Thanks in advance!

Julia
  • 61
  • 2
  • 7
  • hint: forEach callback takes three arguments - the second one is the current index – Jaromanda X Sep 17 '20 at 23:15
  • Unless you're set on `forEach()`, there's no need to use it over a manual loop, where you could just compare both arrays directly in a single iteration. – zcoop98 Sep 17 '20 at 23:18
  • 1
    Are the comparison strings in same order in each array? Or are you trying to find if other array contains same string? – charlietfl Sep 17 '20 at 23:20
  • What do you want to come out of the comparison? Are you making a list of all matches? A count of the total matches? This can impact the approach(es) we would recommend. – zcoop98 Sep 17 '20 at 23:21
  • Sorry, I misspelled the url list. The second string array should all be 'test-2' not 'test-1'. So the url of each pair is not the same, but they are similar. The comparison is made in the same order. My comparison is to extract the website pair's text variables and to see if they are the same or not. – Julia Sep 17 '20 at 23:34
  • 1
    Did you see [How do I zip two arrays in JavaScript?](https://stackoverflow.com/questions/22015684/how-do-i-zip-two-arrays-in-javascript) – Richard Matsen Sep 18 '20 at 00:38

4 Answers4

0

If all you want is to compare values in same position of each array just use the index argument of forEach to reference array element in other array

var FirstList=['https://test1-1/travel','https://test1-1/cook','https://test1-1/eat'];
var SecondList=['https://test1-2/travel','https://test1-1/cook','https://test1-1/eat'];

FirstList.forEach((str, i) => console.log(str === SecondList[i]))
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Sorry my bad, I misspelled the second string list. I just edited my question. Each url string is not the same, but they are similar. So I cannot str === SecondList[i]) to compare them. – Julia Sep 17 '20 at 23:39
0

I think the purpose of a forEach loop is to iterate over 1 list only. I would consider using a generic for loop to serve this purpose.

EDIT: I edited the code, and added a string prototype function to calculate the Levenstein distance between 2 strings. It's not rigid to detect for an edit in the exact spot your strings are changed in the examples. But I expect the examples are probably not totally reflective of your real data anyway, so instead of giving you some questionable regex, I'm giving you Levenstein and hope you understand it doesn't care where the difference is, it just cares how much has changed. In the example I only allow 1 character or less of difference: if (diff <= 1) {

//Define a string function for Levenstein Edit Distance
//call it "distancefrom" for clarity
String.prototype.distancefrom = function(string) {
    var a = this, b = string + "", m = [], i, j, min = Math.min;
    if (!(a && b)) return (b || a).length;
    for (i = 0; i <= b.length; m[i] = [i++]);
    for (j = 0; j <= a.length; m[0][j] = j++);

    for (i = 1; i <= b.length; i++) {
        for (j = 1; j <= a.length; j++) {
            m[i][j] = b.charAt(i - 1) == a.charAt(j - 1)
                ? m[i - 1][j - 1]
                : m[i][j] = min(
                    m[i - 1][j - 1] + 1, 
                    min(m[i][j - 1] + 1, m[i - 1 ][j] + 1))
        }
    }

    return m[b.length][a.length];
}


//Your Code
var FirstList=['https://test1-1/travel','https://test1-1/cook','https://test1-1/eat', 'https://waffles.domain/syrup', 'http://pancakes.webpresence/butter'];
var SecondList=['https://test1-2/travel','https://test1-2/cook','https://test1-2/eat', 'https://waffles.domain/syrups', 'https://pancakes.webpresence/buttery'];

for (let i=0; i < FirstList.length; i++) {
  let diff = FirstList[i].distancefrom(SecondList[i]);
  console.log('"'+FirstList[i]+'" is different than "'+SecondList[i]+'" by '+diff+' characters');
  if (diff <= 1) {
    console.log('Since its less than 1 character of difference, it would technically Pass our test.');
  } else {
    console.log('Since its more than 1 character of difference, it would Fail our test!');
  }
  console.log('-----------------');
}

References: Levenstin Gist by scottgelin on GitHub

Bango
  • 971
  • 6
  • 18
  • Sorry my bad, I misspelled the second string list. I just edited my question. Each url string is not the same, but they are similar. So I cannot FirstList[i] == SecondList[i] to compare them. – Julia Sep 17 '20 at 23:40
0

I think a very similar question was already answered here: How to compare arrays in JavaScript?

Accepted answer (https://stackoverflow.com/a/14853974/1842205) describes in depth how you could achieve such a goal.

JavaScript lacks of such a feature like mentioned zip() method from Python. But we have something like prototyping in JS :). And you can create 2D array like below:

function createArray(length) {
    var arr = new Array(length || 0),
    i = length;

    if (arguments.length > 1) {
       var args = Array.prototype.slice.call(arguments, 1);
       while(i--) arr[length-1 - i] = createArray.apply(this, args);
    }

    return arr;
}

Array.prototype.zip = function (secondArr) {
   let result = createArray(secondArr.length, 2);

   for (let i = 0; i < this.length; i++) {
      result[i][0] = this[i];
      result[i][1] = secondArr[i];
   }

   return result;
};

// usage
var FistList=['https://test1-1/travel','https://test1-1/cook','https://test1-1/eat'];
var SecondList=['https://test1-2/travel','https://test1-2/cook','https://test1-2/eat'];

console.log(JSON.stringify(FistList.zip(SecondList)));
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

I like the OP's idea of making a more functional solution using zip, which can be home-rolled or reused from loadash or underscore.

const firstArray=['https://test1-1/travel','https://test1-1/cook','https://test1-1/eat'];
const secondArray=['https://test1-2/travel','https://test1-2/cook','https://test1-2/eat'];

const zipped = _.zip(firstArray, secondArray)
const compared = zipped.map(([first, second]) => first === second)

console.log(compared)

// reduce the pairwise comparison to a single bool with every()
// depends on requirements, but probably true iff every comparison is true

const arraysMatch = compared.every(e => e)
console.log(arraysMatch)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

Note that more functional solutions often involve the creation of some intermediate arrays (aka garbage) which is fine for small inputs.

danh
  • 62,181
  • 10
  • 95
  • 136