skip to Main Content

Suppose you have a list like this:

[1, 1, 2, 2, 1, 2, 2, 2]

What’s the most efficient way to remove repeated data (not duplicates) so no element appears after itself? For this example, the result should be:

[1, 2, 1, 2]

For example, this could be solved with filter or a for loop remembering the last element. But is there something more elegant? Or which option is most efficient?

for loop:

const arr = [1, 1, 2, 2, 1, 2, 2, 2];
const result = [arr[0]];
let lastElement = arr[0];
for (let i = 1, n = arr.length; i < n; ++i) {
  if (arr[i] !== lastElement) {
    lastElement = arr[i];
    result.push(lastElement);
  }
}

filter:

const result = [1, 1, 2, 2, 1, 2, 2, 2].filter((element, index, arr) => element !== arr[index - 1]);

3

Answers


  1. Just filter with comparing with the previous item:

    const result = [1, 1, 2, 2, 1, 2, 2, 2].filter((item, idx, arr) => !idx || item !== arr[idx - 1]);
    console.log(result);
    Login or Signup to reply.
  2. Reduce and filter are normally slower for large arrays than for loops

    JSPerf on mine, Alexander’s and your code: https://jsperf.app/popose/2

    Your for loop is faster than this (but not by much)

    enter image description here

    const removeRepeated = (data) => {
      const result = [];
      for (let i = 0, len = data.length; i < len; i++) {
        if (i === 0 || data[i] !== data[i - 1]) {
          result.push(data[i]);
        }
      }
      return result;
    };
    
    // Example usage
    const data = [1, 1, 2, 2, 1, 2, 2, 2];
    const result = removeRepeated(data);
    console.log(result); // Expected output: [1, 2, 1, 2]
    Login or Signup to reply.
  3. Your code seems quite optimal. Just one remark: it will fail for an empty array as input, so I would suggest adding a guard for that.

    If it is acceptable to perform the action inplace, mutating the input array instead of creating a new one, you can still get some time gain:

    function removeRepetitionsInplace(arr) {
        if (arr.length < 2) return;
        let k = 0;
        let lastElement = arr[0];
        for (let i = 1; i < arr.length; i++) {
            if (arr[i] !== lastElement) {
                lastElement = arr[++k] = arr[i];
            }
        }
        arr.length = k + 1;
    }
    

    See performance tests at https://jsperf.app/popose/3 (added test case to mplungjan’s)

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search