Created
May 20, 2019 22:12
-
-
Save fakenickels/38947f92db35891dd3cb74b7ae640707 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* actually there is a way to do this with reduce + find but would be really expensive if there are too many elements */ | |
/* Really don't bother with all these now, it's just some optimizations you can do with BuckleScript */ | |
let groupBy = (type a, items, ~key) => { | |
let cmp: (a, a) => int = Pervasives.compare; | |
module Cmp = (val Belt.Id.comparable(~cmp)); | |
let empty = Belt.Map.make(~id=(module Cmp)); | |
let merge = newItem => | |
fun | |
| None => Some([newItem]) | |
| Some(existingItems) => Some([newItem, ...existingItems]); | |
Belt.Array.reduce(items, empty, (map, item) => | |
Belt.Map.update(map, key(item), merge(item)) | |
) | |
|. Belt.Map.map(Array.of_list) | |
|> Belt.Map.toArray; | |
}; | |
let group = (user##events)->groupBy(~key=(event => formatDate(event##date))); | |
if would return something like | |
[|("20-20-2020", [|event1, event2, event3|]), ("12-20-1202", [|event3, event4, event5|])|] | |
which you can loop like | |
result | |
->Belt.Array.map((( label, events )) => { | |
<Group key={label}> | |
<Title value=label /> | |
{events->Belt.Array.map(event, renderEventItem)->React.Array} | |
</Group> | |
}) | |
->React.array | |
``` | |
the other "unoptimized" way would be something like | |
``` | |
let groupBy = (items, ~key) => { | |
items->Belt.Array.reduce([||], (acc, item) => { | |
let itemKey = key(item); | |
let group = Belt.Array.getBy(acc, ((label, _)) => label == itemKey) | |
let newGroup = switch(group) { | |
| Some(( itemKey, currentEls )) => (group, Belt.Array.concat(currentEls, [|item|])) | |
| None => (itemKey, [|item|]) | |
} | |
acc->Belt.Array.keep(((label, _)) => label !== itemKey)->Belt.Array.concat(group) | |
}) | |
} | |
Or with a custom getIndex | |
let getIndex = (items, ~predicate) => { | |
let length = Belt.Array.length(items); | |
let rec find = index => | |
if (index > length) { | |
None; | |
} else { | |
/* Fine because we are hiding the unsafe implementation from the user/implementer */ | |
let el = Belt.Array.getUnsafe(items, index); | |
predicate(el) ? Some(index) : find(index + 1); | |
}; | |
find(0); | |
}; | |
let groupBy = (items, ~key) => { | |
items->Belt.Array.reduce([||], (acc, item) => { | |
let itemKey = key(item); | |
let groupIndex = getIndex(acc, ((label, _)) => label == itemKey) | |
switch(groupIndex) { | |
| Some(index) => get group concat index... and use Belt.Array.set | |
| None => Belt.Array.concat(acc, (itemKey, [|item|])) | |
} | |
}) | |
} | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment