Organise duplicate numbers in list

Viewed 116

Given an array of numbers, a function should return an array of arrays, where each subarray contains all the duplicates of a particular number.

Subarrays should be in the same order as the first occurence of the number they contain. Given this:

[3, 2, 6, 2, 1, 3]

how can i get this

[[3, 3], [2, 2], [6], [1]]
5 Answers

You could take an object for grouping same values.

var array = [3, 2, 6, 2, 1, 3],
    result = [],
    group = {};

for (let value of array) {
    if (!group[value]) result.push(group[value] = []);
    group[value].push(value);
}

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

I believe it can be written shorter and simpler, here is my shot :

function group(arr) {
  let dubArray = []
  arr.forEach((item) => {
    let itemArr = []
    arr = arr.filter((repeatItem)=>{
      if(item === repeatItem) {
        itemArr.push(item)
        return false
      } 
      return true
    })
    if(itemArr.length > 0 )
   dubArray.push(itemArr)
  })
  return dubArray
}

console.log(group([1, 2, 1, 5, 5, 1]))

I made a function that can do that called group.

let test = [3, 2, 6, 2, 1, 3];

function group(list){

 let result = [];
 let used = []

 for (let i = 0; i<list.length; i++){
  let sames = [];

  for (let j = i+1; j<list.length; j++){

   if (list[i] == list[j] && !used.includes(list[i])){
    sames.push(list[j])
   }
   
  }

  if (!used.includes(list[i])){
   sames.push(list[i])
  }
  used.push(list[i]);
  
  if (sames.length > 0){
   result.push(sames)
  }
    
 }

 return result
}

console.log(group(test))

let arr = [3, 2, 6, 2, 1, 3];

let unique_set = []; // storage of first occured unique numbers
let result = [];

arr.forEach(n => {
  let index = unique_set.indexOf(n);
  if( index !== -1 ) return result[index].push(n);
  
  unique_set.push(n);
  result.push( [n] );
  // the index of number in set, and index of result array will always match
});

console.log(result);

O(N)

The Map object is very useful in a situation like this. It's quite efficient, and iterating over the entries is always in the insertion order.

let arr = [3, 2, 6, 2, 1, 3];

// form a Map with number as key sub arrays as value
let aMap = new Map();
arr.forEach(num => {
  if (!aMap.has(num)) { aMap.set(num, []); }
  let subArr = aMap.get(num);
  subArr.push(num);
  aMap.set(num, subArr);
});

// loop through Map to form array of sub-arrays
let counts = [];
aMap.forEach(subArr => {
  counts.push(subArr);
});

const result = document.getElementById('result');
result.innerHTML = 'arr: ' + JSON.stringify(arr) + '\n';
result.innerHTML += 'aMap: {';
aMap.forEach((subArr, number) => {
  result.innerHTML += ` ${number} => ${JSON.stringify(subArr)},`;
});
result.innerHTML += ` }\n`;
result.innerHTML += 'counts: ' + JSON.stringify(counts);
<pre id="result"></pre>

Related