0

I have a nested/multi-dimensional array like so:

[ [ 1, 1, a ], [ 1, 1 , b ], [ 2, 2, c ], [ 1 ,1, d ] ]

And I want to filter it so that it returns only unique values of the outer array based on the 1st value of each nested array.

So from the above array, it would return:

[ [1,1,a] [2,2,c] ]

Am trying to do this in vanilla javascript if possible. Thanks for any input! =)

2
  • what does not work? Commented May 17, 2021 at 16:28
  • Welcome to Stack Overflow! This is not a website where people write code for you so that you don't have to. If you need help debugging code that you have written, you must post a Minimal, Complete, and Verifiable example and explain the specific problem with your code. Commented May 17, 2021 at 16:29

5 Answers 5

1

Here is my solution.

const dedup = arr.filter((item, idx) => arr.findIndex(x => x[0] == item[0]) == idx)

It looks simple and also somehow tricky a bit.

Sign up to request clarification or add additional context in comments.

2 Comments

this code was written ES5. would work for all browsers.
Note that this solution is O(n^2) and therefore not ideal if arr is large.
1

I realize there's already three solutions, but I don't like them. My solution is

  1. Generic - you can use unique with any selector function
  2. O(n) - it uses a set, it doesn't run in O(n^2) time

So here it is:

/**
 * @param arr - The array to get the unique values of
 * @param uniqueBy - Takes the value and selects a criterion by which unique values should be taken
 * 
 * @returns A new array containing the original values
 * 
 * @example unique(["hello", "hElLo", "friend"], s => s.toLowerCase()) // ["hello", "friend"]
 */
function unique(arr, uniqueBy) {
    const temp = new Set()
    return arr.filter(v => {
        const computed = uniqueBy(v)
        const isContained = temp.has(computed)
        temp.add(computed)
        return !isContained
    })
}

const arr = [ [ 1, 1, 'a' ], [ 1, 1, 'b' ], [ 2, 2, 'c' ], [ 1, 1, 'd' ] ]

console.log(unique(arr, v => v[0]))

Comments

0

You could filter with a set and given index.

const
    uniqueByIndex = (i, s = new Set) => array => !s.has(array[i]) && s.add(array[i]),
    data = [[1, 1, 'a'], [1, 1, 'b'], [2, 2, 'c'], [1, 1, 'd']],
    result = data.filter(uniqueByIndex(0));

console.log(result);

Comments

0

const input = [[1,1,'a'], [1,1,'b'], [2,2,'c'], [1,1,'d']]

const res = input.reduce((acc, e) => acc.find(x => x[0] === e[0])
                                                   ? acc
                                                   : [...acc, e], [])
console.log(res)

Comments

-1

Create the object with keys as first element of array. Iterate over array, check if the first element of array exist in the Object, if not push into the array.

const nestedArr = [ [1,1,"a"], [1,1,"b"], [2,2,"c"], [1,1,"d"] ];
const output = {};

for(let arr of nestedArr) {
    if(!output[arr[0]]) {
        output[arr[0]] = arr;
    }
}

console.log(Object.values(output));

Another solution, would be to maintain the count of first array element and if the count is equal to 1, then push in the final array.

const input = [ [1,1,"a"], [1,1,"b"], [2,2,"c"], [1,1,"d"] ],
         count = {},
         output = [];
         
input.forEach(arr => {
    count[arr[0]] = (count[arr[0]] || 0) + 1;
    if(count[arr[0]] === 1)  {
        output.push(arr);
    }
})

console.log(output);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.