最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Remove adjacent duplicates on array - Stack Overflow

programmeradmin1浏览0评论

Suppose we have an array of numbers like the next one:

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

The goal is to remove duplicates values, but only if they are adjacent. So, the expected output for the previous sample should be:

[2, 0, 2, 3, 0, 1]

So far, I managed to almost solve this using a recursive approach, but for some reason that I can't figure, the generated result is not returned (however, you can see it on the log before the returning condition).

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

const remAdjDups = (arr, output = []) =>
{
    if (!arr.length)
    {
        console.log("Result before return: ", output);
        return output;
    }

    if (arr[0] === arr[1])
    {
        arr.splice(1, 1);
        remAdjDups(arr, output);
    }
    else
    {
        remAdjDups(arr.slice(1), output.concat(arr[0]));
    }
}

let out = remAdjDups(input.slice());
console.log("output: ", out);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Suppose we have an array of numbers like the next one:

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

The goal is to remove duplicates values, but only if they are adjacent. So, the expected output for the previous sample should be:

[2, 0, 2, 3, 0, 1]

So far, I managed to almost solve this using a recursive approach, but for some reason that I can't figure, the generated result is not returned (however, you can see it on the log before the returning condition).

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

const remAdjDups = (arr, output = []) =>
{
    if (!arr.length)
    {
        console.log("Result before return: ", output);
        return output;
    }

    if (arr[0] === arr[1])
    {
        arr.splice(1, 1);
        remAdjDups(arr, output);
    }
    else
    {
        remAdjDups(arr.slice(1), output.concat(arr[0]));
    }
}

let out = remAdjDups(input.slice());
console.log("output: ", out);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

So, first and mainly, I will like to understand what is happening with my approach, and second I'm open to any other approach (of any type) that could solve this problem.


Updated Solution

Just in case anyone is interested, I have finally solve this problem using recursion this way. I know filter solution is shorted and elegant, but I was training solving by recursion.

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1, 1, 1, 1];

const remAdjDups = ([x, y, ...rest], out = []) =>
{
    if (!rest.length)
        return (x === y) ? [...out, x] : [...out, x, y];
    else if (x === y)
        return remAdjDups([x, ...rest], out);
    else
        return remAdjDups([y, ...rest], [...out, x]);
}

let out = remAdjDups(input.slice());
console.log("output: ", out);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Share Improve this question edited Aug 7, 2020 at 0:36 Shidersz asked Feb 9, 2019 at 5:10 ShiderszShidersz 17.2k2 gold badges27 silver badges51 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 12

Regarding your solution, just add return before remAdjDups(arr...

P.S.

I used Array.prototype.filter for that

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

const result = input.filter((i,idx) => input[idx-1] !== i)

console.log(result)

You can use filter

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

const result = input.filter((i,index) => {
 if(index != 0){
  return input[index-1] !== i
 } 
 return i
})

console.log(result)

Recursion by mathematical induction works nicely for this problem -

  1. If the first element, a, is null, return the empty result
  2. (induction) the first element is NOT null. If the second element, b, is null, return a singleton array of the first element, a
  3. (induction) neither the first element NOR the second element are null. If a is equal to b, return the recursive result with a removed
  4. (induction) neither the first element nor the second element are null and they are NOT equal to one another. Return the recursive result without removing either a or b

const removeDupes = ([ a, b, ...more ]) =>
  a == null
    ? []                                  // 1
: b == null
    ? [ a ]                               // 2
: a === b
    ? removeDupes([ b, ...more ])         // 3
: [ a, ...removeDupes([ b, ...more ]) ]   // 4

const input =
  [2, 2, 0, 2, 3, 3, 3, 0, 0, 1, 1];

const result =
  removeDupes(input)
  
console.log(result)
// [ 2, 0, 2, 3, 0, 1 ]

Your approach is correct, you just forgot to return the result from the recursive call. All you need is to add return statement.

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1];

const remAdjDups = (arr, output = []) =>
{
    if (!arr.length)
    {
        console.log("Result before return: ", output);
        return output;
    }

    if (arr[0] === arr[1])
    {
        arr.splice(1, 1);
        return remAdjDups(arr, output);
    }
    else
    {
        return remAdjDups(arr.slice(1), output.concat(arr[0]));
    }
}

let out = remAdjDups(input.slice());
console.log("output: ", out);

Hope this will help!

Yo need to use return in the if and else blocks of your code as otherwise undefined is going to be returned.

if (arr[0] === arr[1])
{
    arr.splice(1, 1);
    return remAdjDups(arr, output);
}
else
{
    return remAdjDups(arr.slice(1), output.concat(arr[0]));
}

This is another approach using Array#reduce

const input = [2, 2, 0, 2, 3, 3, 0, 0, 1, 1, 1, 1, 6, 3, 3, 5, 8, 8, 0, -1, -1, 2, 56, 57, 56];

const arr = input.reduce((acc, ele, idx) => {
  if(ele !== input[idx + 1]){
   acc.push(ele)
  }
  return acc;
}, []);

console.log(arr);

发布评论

评论列表(0)

  1. 暂无评论