Is there an inverse of _.groupBy? - lodash

I am using lodash and have grouped an array of objects on a key that they shared; I then do calculations to these objects in these groups but now I need to ungroup.
Is there any way to do this in lodash?
Thanks

You can use _.flatMap() to "ungroup", but it won't restore the original order:
const arr = [2, 3, 4, 2, 3, 4]
const grouped = _.groupBy(arr)
console.log(JSON.stringify(grouped))
const ungrouped = _.flatMap(grouped)
console.log(JSON.stringify(ungrouped))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Related

Is there a way in Kotlin to map through a list, referencing previous values of the new transformation?

Pretty much the title. I want to map through a list to create a new list, but the logic for transforming each element depends on previous values that have been already transformed.
For a simple example, I have a list val myList = [1, 2, 3, 4, 5] and I want to map through each value, where each new value is the sum of the current element plus the previous transformed element. Meaning, I want the result to be [1, 3, 6, 10, 15]. This is not a real scenario, just for sake of example.
I can map through my list but I don't know how to reference the new list that's currently being built:
myList.map { it + list_that's_currently_being_built[i-1] }
runningReduce
fun main() {
val myList = listOf(1, 2, 3, 4, 5)
val result = myList.runningReduce { acc, value -> acc + value }
println(result) // [1, 3, 6, 10, 15]
}

Search predecessors only upto a certain node in cytoscape.js

I can use the predecessors function to find all the predecessors of a node. What I want is to find a predecessor upto a certain.
(The graph is constrained to have that one parent)
Example:
In the above picture, if I call predecessors on node 8, it would give me [1, 2, 3, 4, 5, 6, 7] as the result (ignoring edges).
I want it to limit the search only upto a certain node. If I want it to limit the search until 4, it should return only [4, 5, 6, 7]. Not anything above it.
Is it possible using native cytoscape functions?
The predecessors function accepts selectors and I've tried using that like node.predecessors("node#4 node") according to the docs. But it returned nothing.
I managed to solve it by finding all the successors of the node I'm trying to stop at, then intersecting it with the predecessors of the input node:
const node = cy.$('node#8');
const predecessors = node.predecessors(); // [1, 2, 3, 4, 5, 6, 7]
const requiredRootNode = cy.$('node#4');
const rootChildren = requiredRootNode.successors(); // [5, 6, 7, 8]
const intersection = rootChildren.intersection(predecessors); // [5, 6, 7]
const result = intersection.add(requiredRootNode); // [4, 5, 6, 7]
You can use either use depthFirstSearch or breadthFirstSearch.
The code sample there would allow you to change the visit. Change the following to your liking:
const limitingID = '4';
var bfs = cy.elements().bfs({
roots: '#e',
visit: function(v){
// Stopping at desired node
if( v.id == limitingID ){
return true;
}
},
directed: false
});
var path = bfs.path; // path to found node
var found = bfs.found; // found node

Range with step in Ramda

What's the best way to do the following in Ramda:
_.range(0, 3, 0);
// => [0, 0, 0]
Thank you.
If you need to repeat the same number n times, then Ori Drori already provided a good answer with repeat.
However if you need to support step, you would have to build a function yourself. (Ramda has a range function but it does not support step.)
So where Lodash would return:
_.range(1, 10, 2);
//=> [1, 3, 5, 7, 9]
You can achieve a similar functionality with Ramda unfold function:
const rangeStep = curry((start, end, step) =>
unfold(n => n < end ? [n, n + step] : false, start));
rangeStep(1, 10, 2);
//=> [1, 3, 5, 7, 9]
You can use R.repeat to create an array of multiple instances of a single item:
const result = R.repeat(0, 3)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

Divide list into parts

Is there a simple way to divide list into parts (maybe some lambda) in Kotlin?
For example:
[1, 2, 3, 4, 5, 6] => [[1, 2], [3, 4], [5, 6]]
Since Kotlin 1.2 you can use Iterable<T>.chunked(size: Int): List<List<T>> function from stdlib (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html).
Given the list: val list = listOf(1, 2, 3, 4, 5, 6) you can use groupBy:
list.groupBy { (it + 1) / 2 }.map { it.value }
Or if your values are not numbers you can first assign an index to them:
list.withIndex()
.groupBy { it.index / 2 }
.map { it.value.map { it.value } }
Or if you'd like to save some allocations you can go a bit more manual way with foldIndexed:
list.foldIndexed(ArrayList<ArrayList<Int>>(list.size / 2)) { index, acc, item ->
if (index % 2 == 0) {
acc.add(ArrayList(2))
}
acc.last().add(item)
acc
}
The better answer is actually the one authored by VasyaFromRussia.
If you use groupBy, you will have to add and index and then post-process extracting the value from an IndexedValue object.
If you use chunked, you simply need to write:
val list = listOf(10, 2, 3, 4, 5, 6)
val chunked = list.chunked(2)
println(chunked)
This prints out:
[[10, 2], [3, 4], [5, 6]]
Nice way of dividing list is by the use of function partition. Unlike groupBy it doesn't divide list by keys but rather by predicate which gives out Pair<List, List> as a result.
Here's an example:
val (favorited, rest) = posts.partition { post ->
post.isFavorited()
}
favoritedList.addAll(favorited)
postsList.addAll(rest)
The API says there is a GroupBy function, which should do what you want.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/group-by.html
Or use sublist and break it up yourself
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/sub-list.html
If you want to divide a list into N parts.
(and not divide a list into parts of size N)
You can still use the chunked answer:
https://stackoverflow.com/a/48400664/413127
Only, first you need to find your chunk size.
val parts = 2
val list = listOf(10, 2, 3, 4, 5, 6)
val remainder = list.size % 2 // 1 or 0
val chunkSize = (list.size / parts) + remainder
val chunked = list.chunked(chunkSize)
println(chunked)
This prints out
[[10, 2, 3], [4, 5, 6]]
or when
val parts = 3
This prints out
[[10, 2], [3, 4], [5, 6]]
Interesting answer in Python here: Splitting a list into N parts of approximately equal length

bug or i don't understand "evolve"

When using Ramda.remove() by itself the function takes an array and outputs an array:
const grid = {rows: [1, 2, 3]};
R.remove(1, 1, grid.rows) // output: [1,3]
When I use Ramda.remove() as a transformation function in Ramda.evolve() it becomes an object {"0": 1, "1": 2, "2": 3} instead of an array [1,3]:
const grid = {rows: [1, 2, 3]};
R.evolve({
rows: R.remove(1, 1, grid.rows)
})(grid); // output:{"rows": {"0": 1, "1": 2, "2": 3}}
Do I understand evolve correctly or is a bug?
I imagine what you most likely want is
rows: R.remove(1, 1)
That will give you a function from a list to a shortened version of that list.
Just when writing this issue I realized what's wrong. I had to wrap R.remove in a function or bind the args. Basically, I needed to pass the reference to the function.
rows: () => R.remove(1, 1, grid.rows)