2

I have an array of values similar to:

["100", "330", "22", "100", "4.7", "0.01", "0.01", "330", "0.01", "100", "47", "22", "100", "0.01"]

Using JavaScript I would like to split this array into a number of arrays where only matching strings are in those arrays like this:

["100", "100", "100"]
["330", "330"]
["22", "22"]
["0.01", "0.01", "0.01", "0.01"]
["47"]
["4.7"]

Any help with this would be much appreciated! Thanks!

Alex Morrison
  • 186
  • 5
  • 18

5 Answers5

3

You could collect with a Map and get the values as result.

From inside out:

  • Use Array#reduce with data and use a Map instance as initialValue.
  • As callback take Map#set and collect the values for each group.

Further methods:

  • spread syntax ... for getting all items of an iterable together with

  • logical OR || for having a default value for spreading.

  • Get the values from the map and use it as parameter for

  • Array.from. This generates an array of all values.

var data = ["100", "330", "22", "100", "4.7", "0.01", "0.01", "330", "0.01", "100", "47", "22", "100", "0.01"],
    result = Array.from(data
        .reduce((m, v) => m.set(v, [...m.get(v) || [], v]), new Map)
        .values()
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you, I like this solution! Could you also add a few comments for me to help me understand and learn the code I'm using :) – Alex Morrison Jan 31 '20 at 17:01
3

Use reduce method and Object.values

   //Go thru each value in `arr` array and convert into object with 
   //keys as unique (value in array) and values array of value repetitions.


   {
     "100": ["100", "100"],
     "22": ["22"],
     ...
     ...    
   }

   //Use the Object.values to get the Values as array of arrays

const arr = ["100", "330", "22", "100", "4.7", "0.01", "0.01", 
             "330", "0.01", "100", "47", "22", "100","0.01"];

const updated = Object.values(
  arr.reduce(
    (acc, curr) => (
      (acc[curr] = curr in acc ? [...acc[curr], curr] : [curr]), acc
    ),
    {}
  )
);

console.log(updated);
Siva K V
  • 10,561
  • 2
  • 16
  • 29
1

Here's another take on using reduce to group by the values.

It reduces to an object, which is then transformed to an array of arrays.

let valueArray = ["100", "330", "22", "100", "4.7", "0.01", "0.01", "330", "0.01", "100", "47", "22", "100", "0.01"];

let groupedByValue = Object.values(valueArray
  .reduce((acc, x)=>{
      let arr = acc[x] || [];
      arr.push(x);
      acc[x] = arr;
      return acc;
   },{}));
 
console.log(groupedByValue);

Extra

Here's a version that will group the unique values by the same format.
It was something cooked up when this question was originally completely misunderstood by yours truly. (it happens...)

let valueArray = ["100", "330", "22", "102", "4.7", "0.01", "0.02", "330", "0.01", "101", "47", "23", "100", "0.02"];

let groupedByFormat = Object.values(valueArray
  .reduce((acc, x)=>{
      let val = x.trim();
      let format = val.replace(/\d/g,'0');
      let arr = acc[format] || [];
      if(!arr.includes(val)) {
     arr.push(val);
     acc[format] = arr.sort();
    }
    return acc;
   },{}));
 
console.log(groupedByFormat);
LukStorms
  • 28,916
  • 5
  • 31
  • 45
-1

Here's an example of what you want using Set.

const data = ["100", "330", "22", "100", "4.7", "0.01", "0.01", "330", "0.01", "100", "47", "22", "100", "0.01"];

const unique = new Set(data);
for(let num of unique) {
  console.log(data.filter(d => d == num));
}
igg
  • 2,172
  • 3
  • 10
  • 33
-1

Also it can be done like this:

const {log} = console;
const arr = ["100", "330", "22", "100", "4.7", "0.01", "0.01", "330", "0.01", "100", "47", "22", "100", "0.01"];
log([...new Set(arr)].map( x => arr.filter( y => y === x )));
M.Dmitriy
  • 1
  • 2