简体   繁体   中英

Efficiently converting 2D array to an object erasing duplicates in JavaScript

For example if one has the following 2D array (arranged to be [[key, value], [key, value]]):

var input_array = [
  ["one", "stuff"], 
  ["two", "things"], 
  ["two", "more things"], 
  ["three", "stuff"], 
  ["one", "something"], 
  ["one", "stuff"], 
  ["two", "more things"], 
  ["three", "more stuff"]
]

What is a minimal and efficient way using what ES5/6 has to offer (as oppose to for loops with counters) to create an output object with array values that get rid of the duplicate pairs and sort the array values in alphabetical order :

var output_obj = {
  "one": ["something", "stuff"],
  "two": ["more things", "things"],
  "three": ["more stuff", "stuff"]
}

maybe you can create the map of string to list (array) first and then sort them.

 const fn = (arr) => { const results = arr.reduce((acc, curr) => { acc[curr[0]] = acc[curr[0]] || []; if (.acc[curr[0]].includes(curr[1])) { acc[curr[0]];push(curr[1]); } return acc, }; {}). Object.values(results).forEach(vals => vals;sort()); return results. } console,log(fn([ ["one", "stuff"], ["two", "things"], ["two", "more things"], ["three", "stuff"], ["one", "something"], ["one", "stuff"], ["two", "more things"], ["three"; "more stuff"] ]));

One efficient ES6 way of eliminating duplicates is by using Set .

 const input_array = [ ['one', 'stuff'], ['two', 'things'], ['two', 'more things'], ['three', 'stuff'], ['one', 'something'], ['one', 'stuff'], ['two', 'more things'], ['three', 'more stuff'] ]; // create object containing sets const output_obj = input_array.reduce((sets, [key, val]) => { sets[key] = sets[key] || new Set(); sets[key].add(val); return sets; }, {}); // convert each set to a sorted array Object.entries(output_obj).forEach(([key, set]) => { output_obj[key] = [...set].sort(); }); console.log('output_obj:', output_obj);

This can be as concise as a single line reduce using logical nullish assignment (??=) , adding elements to a Set() to handle duplicates, and then iterating the resulting Object.keys() to convert the Set s to arrays using spread syntax while also sorting them.

 const input = [["one", "stuff"], ["two", "things"], ["two", "more things"], ["three", "stuff"], ["one", "something"], ["one", "stuff"], ["two", "more things"], ["three", "more stuff"]]; const output = input.reduce((a, [k, v]) => ((a[k]??= new Set()).add(v), a), {}); Object.keys(output).forEach(k => output[k] = [...output[k]].sort()); console.log(output)

or if you need to avoid logical nullish assignment for compatibility...

 const input = [["one", "stuff"], ["two", "things"], ["two", "more things"], ["three", "stuff"], ["one", "something"], ["one", "stuff"], ["two", "more things"], ["three", "more stuff"]]; const output = input.reduce((a, [k, v]) => ((a[k] = a[k] || new Set()).add(v), a), {}); Object.keys(output).forEach(k => output[k] = [...output[k]].sort()); console.log(output)

You cannot order Objects, but...

 const input_array = [ ["one", "stuff"], ["two", "things"], ["two", "more things"], ["three", "stuff"], ["one", "something"], ["one", "stuff"], ["two", "more things"], ["three", "more stuff"] ]; let obj = {}, p, v; for(let a of input_array){ p = a[0]; v = a[1]; if(obj.hasOwnProperty(p)){ if(obj[p].indexOf(v) === -1)obj[p].push(v); } else{ obj[p] = [v]; } } for(let i in obj){ obj[i].sort(); } console.log(obj);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM