0

Suppose I have the following code:

let array = [[1,2,3],[1,3,2],[2,3,1],[1,2,3],[2,4,5]]
I want to have only a unique array which contains only unique combinations of the inner array contents. The final output should be: array = [[1,2,3],[2,4,5]]. The inner array with the most occurrence should be on top of the new array.How to I do that?
Elon Musk
  • 354
  • 2
  • 5
  • 15

3 Answers3

4

Sort them, and use a Set for duplicates:

const dupes = new Set();

const result = array.filter(arr => {
 const key = arr.sort().join("_");
 return !dupes.has(key) && dupes.add(key);
});

To sort them after their appearances, we have to count the appearances in the original array, then sort:

 const appeared = new Map();

 const result = array.filter(arr => {
   const key = arr.sort().join("_");
   return !appeared.has(key) && appeared.set(key, (appeared.get(key) || 0) + 1);
 }).sort((a, b) => appeared.get(a.join("_")) - appeared.get(b.join("_")));
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

@yuvraj, you can solve this problem by using the concept of Set() and join(), split(), map(), sort() methods.

Set() may be a new concept for new JavaScript programmers. Here is an article as Sets in JavaScript - GeeksforGeeks which has a clear, nice and brief explanation for the Sets().

✓ Here, I have tried to show this step by step with a simple example.

Please comment if the code example doesn't satisfy your need. I will update the based on your provided inputs and expected outputs.

Here at http://rextester.com/AVPXM70965, you can find the code on online IDE.

var a = [1, 2, 3]
var b = [1, 2, 3]
var c = [3, 2, 1]

console.log(a.join("") === b.join("")) // true

console.log(a.join("") === c.join("")) // false

console.log(a.join("") === c.sort().join("")) // true

console.log(a.sort().join("") === c.sort().join("")) // true

✓ Finally

var array = [[1,2,3],[1,3,2],[2,3,1],[1,2,3],[2,4,5]]
texts = array.map((arr) => arr.sort().join(":"))
console.log(texts)

var unique_texts = new Set(texts)
console.log(unique_texts)
/*
[ '1:2:3', '1:2:3', '1:2:3', '1:2:3', '2:4:5' ]
Set { '1:2:3', '2:4:5' }
*/

var new_array = []
unique_texts.forEach((item) => {
    var arr = item.split(":").map(num => parseInt(num))
    new_array.push(arr)
})

console.log(new_array)
// [ [ 1, 2, 3 ], [ 2, 4, 5 ] ]
hygull
  • 8,464
  • 2
  • 43
  • 52
0

Essentially you need a counter and a bit of code to get the key, value pairs back to an array. Lodash has an implementation of a counter and a lot of other useful functions.

let array = [
  [1, 2, 3],
  [1, 3, 2],
  [2, 3, 1],
  [1, 2, 3],
  [2, 4, 5]
];

// count by the sorted elements 
const counter = _.countBy(array, inner => inner.slice().sort());
// counter is of form: {"2,4,5":1, ...}
// let's use lodash to make an array of [key, value] pairs
const pairs = _.toPairs(counter);
// sort by desc popularity (hence the minus)
const sortedByPopularity = _.sortBy(pairs, pair => -pair[1]);
// convert the "1,2,3" keys back to arrays of numbers
const result = sortedByPopularity.map(pair => pair[0].split(',').map(Number));

console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
vassiliskrikonis
  • 566
  • 2
  • 10