0

I would like to return a new array made of arrays from an array of dictionaries that are to be sorted. I might not be explaining properly but I will just give examples of what I am trying todo.

So I have the following:

let foo = [{"id": "hello123"}, {"id":"goodbye123"}, {"id":"hello123"}];

I would like to sort it by the id value and return an array of array dictionary like so:

let bar = sortByKey(foo, "id");
console.log(bar);

output = [[{"id":"hello123"},{"id":"hello123"}],[{"id":"goodbye123"}]]

So far all I know how todo is sort it so that the outcome looks like:

[{"id":"hello123"},{"id":"hello123"},{"id":"goodbye123"}]
8
  • 2
    Where is your sortByKey function? What is the code that you've tried that isn't working? Commented Apr 30, 2019 at 8:43
  • 2
    what qualifies the sort order? Commented Apr 30, 2019 at 8:44
  • 3
    That's not sorting, that's partitioning. Commented Apr 30, 2019 at 8:47
  • @CertainPerformance the sortByKey function hasn't been made yet. currently using this foo.sort((a,b) => (a.id > b.id) ? 1 : ((b.id > a.id) ? -1 : 0)); from another post to sort it by id's value. Commented Apr 30, 2019 at 8:48
  • 1
    You may just want to take unique values, sort them and partition them: jsfiddle.net/zp9eh2dc/1 . Otherwise you can use Array.reduce to make it more efficient Commented Apr 30, 2019 at 8:49

2 Answers 2

2

You could use a hash table for the groups and Array#reduce for iterating the array and assigns all object to their groups.

Later return all values from the hash table.

function groupBy(array, group) {
    return Object.values(array.reduce((hash, o) => {
        hash[o[group]] = hash[o[group]] || [];
        hash[o[group]].push(o);
        return hash;
    }, Object.create(null)));
}

var data =  [{ id: "hello123" }, { id: "goodbye123" }, { id: "hello123" }];
	
console.log(groupBy(data, "id"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

The same with a Map and slightly shorter.

function groupBy(array, group) {
    return Array.from(array
        .reduce((m, o) => m.set(o[group], [...(m.get(o[group]) || []), o]), new Map)
        .values()
    );
}

var data =  [{ id: "hello123" }, { id: "goodbye123" }, { id: "hello123" }];
	
console.log(groupBy(data, "id"));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. this does exactly what I need and works with big data too. I will go study it properly now so now I know what is happening instead of blindly using it. Thank you again :)
1

Just for the sake of providing another solution (despite @NinaScholz's solution is way better), here is a solution relying on Set, map and filter:

let foo = [{"id": "hello123"}, {"id":"goodbye123"}, {"id":"hello123"}];

function sortByKey(arr, key) {
	const _uniqueValues = [...new Set(foo.map(i => i[key]))].sort((a,b) => (a[key] > b[key]) ? 1 : ((b[key] > a[key]) ? -1 : 0));
  return _uniqueValues.map(v => arr.filter(i => i[key] === v));
}

console.log(sortByKey(foo, 'id'));

This will take unique values (using Set) first and sort them, then it will map them by partitioning the original array using filter. The reduce solution will be more efficient, but it's still a possible way to do this.

Please accept / read @NinaScholz's solution below, this is just an alternative to the solution provided. Using reduce is the correct approach

2 Comments

Still like yours for the fact that I can understand whats going on slightly better but for the sake of efficiency I will give the answer to nina scholz instead. But thank you for the quick solution :)
@MarcoFernandes I think Nina won't mind explaining you what's going on in her solution, though ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.