3

I have an array of objects in javascript (D3) and I need to remove every object of which a certain attribute is present in another array of objects attribute,
i.e. a left outer join full outer join
(source: tazindeed.co.uk)

I managed to do it myself with 2 loops but it's quite slow.
And I don't know how to make it faster.

    for (var i = 0; i < data1.length; i++) {
        for (var j = 0; j < data2.length; j++) {
            if (data2[j].attr3 == data1[i].attr4) {
                data2.splice(j,1);
            }
        }
    }

data1.length~2k and data2.length~10k

I know this has approximately been asked here but it's been almost 2 years and the solutions use external libraries.
I'm just curious to learn if there is a better method with javascript (or jQuery or D3, which I already use)

Thank you for your help !

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
stallingOne
  • 3,633
  • 3
  • 41
  • 63

3 Answers3

4

You need a fast lookup for the values that exist in data1, so make a map using an object:

var map = {};
for (var i = 0; i < data1.length; i++) {
  map[data1[i].attr4] = 1;
}

Then you can loop throught the items in data2 and filter them:

var result = [];
for (i = 0; i < data2.length; i++) {
  if (!(data2[i].attr3 in map)) {
    result.push(data2[i]);
  }
}
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • good answer just a note: if you must apply this kind of logic for arrays all over your app you can take a look on underscore – jean Mar 02 '15 at 13:08
4

Maybe not faster but more readable

const left = ['1', '2', '7']
const right = ['1', '3', '5', '9']

const result = left.filter((x) => !right.includes(x))
Yoruba
  • 2,572
  • 22
  • 26
  • note that you'll have to use [`array.some`](https://stackoverflow.com/a/47642827/6908282) if you need a more complex condition to filter. Additional Reference: [`.includes()` vs `.some()`](https://stackoverflow.com/a/64946579/6908282) – Gangula Sep 02 '22 at 10:01
3

You could use Array.filter (see MDN) or Array.map for that I suppose:

var array1 = [1,2,3,4,5,6,7,8,9],
    array2 = [3,4,5,6],
    fltr   = array1.filter( function(v) {return this.indexOf(v) < 0;}, array2),
    map    = array1.map( 
              function(v) {
                 var exists = this.indexOf(v);
                 return [v, (this[exists] || 'null')].join(', ');}, 
              array2),
    result = document.querySelector('#result');
fltr.unshift('<u>array1</u>');
map.unshift('<u>array1, array2</u>');
result.innerHTML = ['<b>filtered</b>\n',
                     fltr.join('\n'),
                    '\n\n<b>mapped</b>\n',
                     map.join('\n')].join('');
  
<pre id="result"></pre>
KooiInc
  • 119,216
  • 31
  • 141
  • 177