user13849624
user13849624

Reputation:

remove duplicate elements in proceeding arrays inside array of arrays

We have an array of arrays like this:

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14]
]; 

There may be duplicate elements in each array and that's fine.

But I'm after a proper solution to remove duplicate elements in each set comparing to lower sets!

So as we have a 0 in the first array and the last array, we should consider the 0 in last one a duplication and remove it...

the desired result would be:

[0, 1, 2, 3, 4, 4, 4, 4],
[5, 6, 7, 8, 9, 10, 11, 11],
[12],
[14]

It's a confusing issue for me please help...

Upvotes: 5

Views: 172

Answers (6)

Mechanic
Mechanic

Reputation: 5380

Simple, clean and high performance solution:

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14]
]; 

const duplicates = {};

const answer = arrays.map( (array, level) => {
  return array.filter( el => {
    if ( duplicates[el] < level ) {
      // return nothing; fine
    } else {
      duplicates[el] = level;
      return el
    }
  })
});

console.log(JSON.stringify(answer))

here is on-liner and less-readable form:

const d = {}, arrays = [ [0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]];

const answer = arrays.map((a,l)=> a.filter(el=> d[el]<l ? 0 : (d[el]=l,el)));

console.log(JSON.stringify(answer))

Upvotes: 0

There are plenty of inefficient ways to do this, but if you want to do this in O(n), then we can make the observation that what we want to know is "which array a number is in". If we know that, we can run our algorithm in O(n):

for every element e in array at index i:
  if index(e) == i:
    this is fine
  if index(e) < i:
    remove this e

So let's just do literally that: we allocate an object to act as our lookup, and then we run through all elements:

const lookup = {};

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14]
];

const reduced = arrays.map((array, index) => {
  // run through the elements in reverse, so that we can
  // safely remove bad elements without affecting the loop:
  for(let i=array.length-1; i>=0; i--) {
    let value = array[i];
    let knownIndex = (lookup[value] ??= index);
    if (knownIndex < index) {
      // removing from "somewhere" in the array
      // uses the splice function:
      array.splice(i,1);
    }
  }
  return array;
});

console.log(reduced);

For an alternative, where the loop+splice is taken care of using filter, see Nina's answer.

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386540

You could collect the values in an object with index as value, and filter for values who are at the same index.

const
    arrays = [[0, 1, 2, 3, 4, 4, 4, 4], [5, 6, 7, 8, 9, 10, 11, 11], [2, 7, 10, 12], [0, 7, 10, 14]], 
    seen = {},
    result = arrays.map((array, i) => array.filter(v => (seen[v] ??= i) === i));

result.forEach(a => console.log(...a));

Upvotes: 6

Angel Zlatanov
Angel Zlatanov

Reputation: 328

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14],
];

const output = arrays.reduce(
  ({ output, set }, current, i) => {
    output[i] = current.filter((num) => !set.has(num));
    [...new Set(output[i])].forEach((num) => set.add(num));
    return { output, set };
  },
  { output: [], set: new Set() }
).output;

console.log(output);

Gets the exact output you want:

[
  [
    0, 1, 2, 3,
    4, 4, 4, 4
  ],
  [
    5,  6,  7,  8,
    9, 10, 11, 11
  ],
  [ 12 ],
  [ 14 ]
]

Upvotes: -1

Fullstack Guy
Fullstack Guy

Reputation: 16908

We can do this using Array#reduce and maintain a seen Set, which will have all visited numbers from each array.

Once you iterate over an array you push all visited elements in the seen Set, then push a new array filtered by the elements not in the seen Set:

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14]
]; 

const removeDupsInSibling = (arr) => {
  let seen = new Set();
  return arr.reduce((acc, a)=> {
    const f = a.filter(v => !seen.has(v));
    seen = new Set([...seen, ...a]);
    acc.push(f);
    return acc;
  }, []);
}

console.log(removeDupsInSibling(arrays));

Upvotes: 0

Δ O
Δ O

Reputation: 3710

const arrays = [
  [0, 1, 2, 3, 4, 4, 4, 4],
  [4, 4, 5, 6, 7, 8, 9, 10, 11, 11],
  [2, 7, 10, 12],
  [0, 7, 10, 14]
]

let filtered = arrays.map((row, i) => {
  // concat all previous arrays
  let prev = [].concat(...arrays.slice(0, i))
  // filter out duplicates from prev arrays
  return row.filter(r => !prev.includes(r))
})

console.log(filtered)

Upvotes: 0

Related Questions