Compare values of two arrays and generate a third with the unique javascript values

Asked

Viewed 199 times

2

I am doing, with google script, a very simple system that monitors the progress of daily activities, I have a table with the requested activities, a table with the interactions and a table with the status (open or closed). I need to compare the list with the ID’s of the requested activities with the list with the ID’s of the closed activities. The remaining Ids I assume are open. Note: I am beginner in programming, can correct me the will!

function arrayabertas(){
var todos = [08072020105842, 08072020110953, 8072020104528];
var fechado = [8072020104528];
var abertos = [];

// Verifica se cada número jogado
// está na lista dos sorteados
for(var i=0; i<fechado.length; i++) {
    if(todos.indexOf(fechado[i]) > -1) {
        abertos.push(fechado[i]);
    }
}
    return(abertos);
}

  • 1

    Julio, you cannot keep changing the question because it invalidates the existing answers. If you have another question, please do it here. And I suggest that in this new question you put an example of the spreadsheet so that people can test (because only with images does not give)

  • 1

    And if one of the answers solved your problem (the specific problem that is in your question, the way you put it, not the spreadsheet problem), you can choose the one that best solved it and accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. Don’t forget that you can also vote in all the answers you found useful.

  • 1

    Don’t take this the idea of the site is to have a specific problem per question. If you have another question (even if it is related), then the ideal is to ask another one. Changing the question goes against the idea of the site and makes it more disorganized: https://pt.meta.stackoverflow.com/a/1684/112052

  • 1

    Okay, all right, I appreciate the comments and help, I’m still beginner in this, I’ll pay attention to how to use the site, thank you!

3 answers

3


If you’re already using compatible environments Ecmascript 2015, an alternative is to use Set, who already owns good support of current browsers.

The Set ensures that its elements will be unique (which is one of your requirements), and also has some operations that facilitate the algorithm for what you need (in addition to being more efficient, as we will see at the end).

For example, in your case, creating a Set with all values and remove the ones that are closed. What is left are the open items:

let todos = [ 08072020105842, 08072020110953, 8072020104528 ];
let fechado = [ 8072020104528 ];

let abertos = new Set(todos);
for (let e of fechado) { // remove todos os fechados
    abertos.delete(e);
}

// converter para array
abertos = Array.from(abertos);
console.log(abertos);


The other answers suggest using indexOf or includes, which actually work (except with includes you should check which elements nay are in fechado, that is to say, abertos = todos.filter(x => ! fechado.includes(x))), but are more inefficient because so much indexOf how much includes traverse the array todos from the start.

That is, for each element of fechado, you have to go through the array todos from the beginning, until you find the element. And when you go through the same array several times, you are creating a variation of the call Shlemiel the Painter’s Algorithm, which is extremely inefficient.

Of course, for small arrays - as is your case - the difference will be insignificant and maybe this is just micro-optimization. But for larger arrays the difference is significant.

Obviously, if this is running on older browsers that do not support Set, then the way is to use indexOf or includes even.


Another detail is that if you are using a function to check open items, it is interesting to receive arrays todos and fechado as parameters, because this way the function becomes more generic and reusable, being able to receive any arrays (as you did, it only works for the informed arrays). Would look like this:

function verificarAbertos(todos, fechado){
    let abertos = new Set(todos);
    for (let e of fechado) {
        abertos.delete(e);
    }
    
    // converter para array
    return Array.from(abertos);
}

let todos = [08072020105842, 08072020110953, 8072020104528];
let fechado = [8072020104528];
let abertos = verificarAbertos(todos, fechado);
console.log(abertos);

// posso passar outros arrays também
console.log(verificarAbertos([1,2,3,4,5,6], [3,4,5])); // [1, 2, 6]

2

Utilize filter with includes, where this filter will be satisfactory only when it has contained the tested value, example:

var todos = [08072020105842, 08072020110953, 8072020104528];
var fechado = [8072020104528];
var abertos = todos.filter(x => fechado.includes(x)); 

console.log(abertos);

References:

  • 1

    The simplest answer and practice without doing too much juggling with the arrays, only thing to adjust would be to deny fechado.includes(x) since abertos shall contain elements which do not exist in fechado, otherwise perfect.

1

Your algorithm is wrong, it checks which elements in todos are also closed, when in fact should check which are NOT closed.

function arrayabertas(){
  var todos = [08072020105842, 08072020110953, 8072020104528];
  var fechado = [8072020104528];
  var abertos = [];

  // Verifica se cada número jogado
  // está na lista dos sorteados
  for(var i=0; i<todos.length; i++) {
    // verifica qual em "todos" não está fechado
    if(fechado.indexOf(todos[i]) === -1) {
      abertos.push(todos[i]);
    }
  }
  return(abertos);
}

You can use the function filter to make the code cleaner

function arrayabertas(){
  var todos = [08072020105842, 08072020110953, 8072020104528];
  var fechado = [8072020104528];
  var abertos = [];

  abertos = todos.filter((x) => fechado.indexOf(x) === -1)

  return(abertos);
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.