Red Wing Justice Chan
Red Wing Justice Chan

Reputation: 159

Jquery check if one array contains same value

I have an simple javascript array that may contain duplicates or maynot contain duplicates.

var names = [
['aaa','pin/test1.html'],
['bbb','pin/test2.html'],
['ttt','test.html'],
['ggg','test.html'],
['yyy','un/777.html'],
['ggg','test3.html'],
['nnn','test3.html'],
['eee','n/777.html'],
['sss','pin/test1.html'],
['xxx','pin/test2.html'],
['ppp','pin/test1.html'],
];

I need to find the duplicate filepath and put their name into new array. If there is no duplicate then assign its name in first and then assign '' after two values. I could point all the codes that I have tried but it doesnt work. I accept jquery solution also. The expected outcome is this.

var outcome = [
[['aaa','sss','ppp'], 'pin/test1.html'],
[['bbb','eee','xxx'], 'pin/test2.html'],
[['ttt','ggg',''], 'test.html'],
[['yyy','',''], 'un/777.html'],
[['ggg','nnn',''], 'test3.html'],
];

What I have tried is this

for (var i = 0; i < arr.length; i++) {
    var uniqueNames = [];
    $.each(arr[i], function (i, el) {
        if ($.inArray(el, uniqueNames) === -1) uniqueNames.push(el);
    });
    console.log(uniqueNames);
}

Upvotes: 0

Views: 178

Answers (3)

Nina Scholz
Nina Scholz

Reputation: 386550

You could take a hash table and an array of empty strings and find the next slot for the value.

The array is reduced by taking an object as accumulator and a destructure array as value (the first part of the array) and key (the second part, aka filepath).

Inside of Array#reduce, a property check with the key is made and if undefined, an array with the wanted structure (array with two items, the first is an array with three emty spaces and the key) is being assigned by using a logical nullish assignment ??=.

The next line assigns the value to the next free slot, an item with an empty string.

Finally the accumulator is returned.

To get only an array as result, a conversion of the values of the object takes place.

let names = [['aaa','pin/test1.html'], ['bbb','pin/test2.html'], ['ttt','test.html'], ['ggg','test.html'], ['yyy','un/777.html'], ['ggg','test3.html'], ['nnn','test3.html'], ['eee','n/777.html'], ['sss','pin/test1.html'], ['xxx','pin/test2.html'], ['ppp','pin/test1.html']],
    grouped = Object.values(names.reduce((r, [v, k]) => {
        r[k] ??= [Array(3).fill(''), k];
        r[k][0][r[k][0].indexOf('')] = v;
        return r;
    }, {}));

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

haynar
haynar

Reputation: 6030

You do not need jQuery for dealing with regular JS structure, you can achieve what you want with a simple code like this:

var names = [['aaa','pin/test1.html'],['bbb','pin/test2.html'],['ttt','test.html'],['ggg','test.html'],['yyy','un/777.html'],['ggg','test3.html'],['nnn','test3.html'],['eee','n/777.html'],['sss','pin/test1.html'],['xxx','pin/test2.html'],['ppp','pin/test1.html'],];

let lengthToFill = 0;
// collecting all the duplicates into a map
const pathMap = {};
names.forEach(name => {
    // just in case if you're not familiar with array destructuring
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
    const [pathName, path] = name;

    // make sure we have an array to deal with
    // just in case you're not familiar with Nullish coalescing operator (??)
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator
    pathMap[path] = pathMap[path] ?? [];
    pathMap[path].push(pathName);

    // tracking the max number of elements we're adding into a single entry
    lengthToFill = Math.max(lengthToFill, pathMap[path].length);
});

const result = Object.entries(pathMap).map(entry => {
    // constructing new array entry based on the data we've collected so far
    return [
        entry[1].concat(Array(lengthToFill - entry[1].length).fill('')),
        entry[0],
    ];
});

console.log(result);

This solution will work for any number of elements that you'd like to fill the array with ''. It makes sure that the length of final listing is the same for all entries.

Upvotes: 0

urchmaney
urchmaney

Reputation: 618

   const aux = (names) => {
    const hash = {};
    let max = 0;
    names.forEach(ele => {
      if (!hash[ele[1]]) hash[ele[1]] = [];
      hash[ele[1]].push(ele[0]);
      max = Math.max(hash[ele[1]].length, max);
    });
  
    return Object.keys(hash).map(ele => [[...hash[ele], ...Array(max -hash[ele].length).fill("")], ele]);
   
   }
   
    var names = [
    ['aaa','pin/test1.html'],
    ['bbb','pin/test2.html'],
    ['ttt','test.html'],
    ['ggg','test.html'],
    ['yyy','un/777.html'],
    ['ggg','test3.html'],
    ['nnn','test3.html'],
    ['eee','n/777.html'],
    ['sss','pin/test1.html'],
    ['xxx','pin/test2.html'],
    ['ppp','pin/test1.html'],
     ];
    console.log(aux(names))

This might help

Upvotes: 0

Related Questions