How do I obtain a rolling buffer of the last two items emitted from a reactive stream? - operators

I have a stream that emits numbers x. What I want is dx (difference in x) so I need a rolling buffer which emits x_n and x_(n-1) so I can map to dx = x_n - x_(n-1). In a marble diagram this would look like ...
SOURCE --A------B------C--------D------F--G-----
RESULT ---------AB-----BC-------CD-----DF-FG----
This would be handy for other operations like rolling averages etc.
I have checked the operator docs but can't seem to find anything similar. sample is sort of close but is time dependent. buffer is also close but it strictly queues values with no overlap between the buffers.
I'm using RxJS

RXJS 5
RxJS has the bufferCount operator which works as follows ...
observable = Rx.Observable.from(["A", "B", "C", "D", "E", "F"])
bufferSize = 2
overlap = 1
observable.bufferCount(bufferSize, overlap)
.subscribe(vals => console.log(vals));
// Results in,
//
// ["A", "B"]
// ["B", "C"]
// ...
overlap is actually the sample frequency so for example in the above case if overlap = 2 then we would get the normal buffer behaviour.

RXJS 4
You maybe don't even need a buffer for this, a simple concatMap might work for you (of course I don't know any details of your stream:
observable = Rx.Observable.from(["A", "B", "C", "D", "E", "F"]);
observable
.bufferWithCount(2, 1)
.subscribe(all => {
console.log(all);
});
See live here

Two options that will work regardless of the version:
Better
Pairwise
Rx.Observable.from(["A", "B", "C", "D", "E", "F"])
.pairwise()
.subscribe(all => {
console.log(all);
});
bufferCount (or bufferWithCount)
This does exist in RxJS 4 as well as RxJS 5
version == 5.* .* ===> bufferCount
version >= 4.1.0 ===> bufferCount
version < 4.1.0 ===> bufferWithCount
Rx.Observable.from(["A", "B", "C", "D", "E", "F"])
// Buffers of length 2 and skip 1 item (i.e. overlap)
.bufferCount(2, 1)
// the last buffer will have only the last item so drop it
.filter(x => x.length == 2)
.subscribe(all => {
console.log(all);
});
See both here

observable = Rx.Observable.from(["A", "B", "C", "D", "E", "F"]);
we can do
observable
.scan((x, y) => [_.last(x), y], [])
.filter((x) => x[0] !== undefined)
.subscribe(all => {
console.log(all);
});
or if a hot observable:
observable.
zip(observable.skip(1))
.subscribe(all => {
console.log(all);
});
or if a cold observable:
observable
.publish(source_ => source_.zip(source_.skip(1)))
.subscribe(all => {
console.log(all);
});
or easiest:
observable
.pairwise()
.subscribe(all => {
console.log(all);
});

Related

Display discrepancies between collections

When asserting the equality of two string collections using
collectionA.Should().Equal(collectionB) the message is:
"Expected collectionA to be equal to {"a", "b", "c", …5 more…} , but {"a", "b", "c", …13 more…} contains 8 item(s) too many."
Is there a way to display the actual discrepancies between the collections?

Matching dynamic keys in karate

I am trying to match a JSON array with a predefined expected json. The problem is that one of the key values in actual JSON is a set of strings delimited by "|". Here is how it looks :
actualJSON = [
{
"a": "varA",
"mix: "X|Y|Z",
},
{
"b": "B",
"c": "C"
} ]
expectedJSON = [
{
"a": "varA",
"mix: "Y|Z|X",
},
{
"b": "B",
"c": "C"
} ]
Issue here is the mix key that represents a set of strings and the value can be any combination of "X|Y|Z" without any specific order like "Z|Y|X" etc. When the value of mix is Y|Z|X then
* match actualJSON contains expectedJSON
works fine but in other cases it fails as expected. Is there a way to do the matching when key value is dynamic?
My first suggestion is as far as possible to write tests where the response is 100% predictable and don't waste time on these weird cases. Also refer: https://stackoverflow.com/a/50350442/143475
That said this is easy to do if you write a JS function:
* def response = { foo: 'X|Y|Z' }
* def hasXyz = function(x){ return x.includes('X') && x.includes('Y') && x.includes('Z') }
* match response == { foo: '#? hasXyz(_)' }
I leave it to you to figure out better logic if you want. Refer: https://github.com/karatelabs/karate#self-validation-expressions

Ramda.js - how to view many values from a nested array

I have this code:
import {compose, view, lensProp, lensIndex, over, map} from "rambda";
let order = {
lineItems:[
{name:"A", total:33},
{name:"B", total:123},
{name:"C", total:777},
]
};
let lineItems = lensProp("lineItems");
let firstLineItem = lensIndex(0);
let total = lensProp("total");
My goal is to get all the totals of all the lineItems (because I want to sum them). I approached the problem incrementally like this:
console.log(view(lineItems, order)); // -> the entire lineItems array
console.log(view(compose(lineItems, firstLineItem), order)); // -> { name: 'A', total: 33 }
console.log(view(compose(lineItems, firstLineItem, total), order)); // -> 33
But I can't figure out the right expression to get back the array of totals
console.log(view(?????, order)); // -> [33,123,777]
That is my question - what goes where the ????? is?
I coded around my ignorance by doing this:
let collector = [];
function collect(t) {
collector.push(t);
}
over(lineItems, map(over(total, collect)), order);
console.log(collector); // -> [33,123,777]
But I'm sure a ramda-native knows how to do this better.
It is possible to achieve this using lenses (traversals), though will likely not be worth the additional complexity.
The idea is that we can use R.traverse with the applicative instance of a Const type as something that is composable with a lens and combines zero or more targets together.
The Const type allows you to wrap up a value that does not change when mapped over (i.e. it remains constant). How do we combine two constant values together to support the applicative ap? We require that the constant values have a monoid instance, meaning they are values that can be combined together and have some value representing an empty instance (e.g. two lists can be concatenated with the empty list being the empty instance, two numbers can be added with zero being the empty instace, etc.)
const Const = x => ({
value: x,
map: function (_) { return this },
ap: other => Const(x.concat(other.value))
})
Next we can create a function that will let us combine the lens targets in different ways, depending on the provided function that wraps the target values in some monoid instance.
const foldMapOf = (theLens, toMonoid) => thing =>
theLens(compose(Const, toMonoid))(thing).value
This function will be used like R.view and R.over, accepting a lens as its first argument and then a function for wrapping the target in an instance of the monoid that will combine the values together. Finally it accepts the thing that you want to drill into with the lens.
Next we'll create a simple helper function that can be used to create our traversal, capturing the monoid type that will be used to aggregate the final target.
const aggregate = empty => traverse(_ => Const(empty))
This is an unfortunate leak where we need to know how the end result will aggregated when composing the traversal, rather than simply knowing that it is something that needs to be traversed. Other languages can make use of static types to infer this information, but no such luck with JS without changing how lenses are defined in Ramda.
Given you mentioned that you would like to sum the targets together, we can create a monoid instance that does exactly that.
const Sum = x => ({
value: x,
concat: other => Sum(x + other.value)
})
This just says that you can wrap two numbers together and when combined, they will produce a new Sum containing the value of adding them together.
We now have everything we need to combine it all together.
const sumItemTotals = order => foldMapOf(
compose(
lensProp('lineItems'),
aggregate(Sum(0)),
lensProp('total')
),
Sum
)(order).value
sumItemTotals({
lineItems: [
{ name: "A", total: 33 },
{ name: "B", total: 123 },
{ name: "C", total: 777 }
]
}) //=> 933
If you just wanted to extract a list instead of summing them directly, we could use the monoid instance for lists instead (e.g. [].concat).
const itemTotals = foldMapOf(
compose(
lensProp('lineItems'),
aggregate([]),
lensProp('total')
),
x => [x]
)
itemTotals({
lineItems: [
{ name: "A", total: 33 },
{ name: "B", total: 123 },
{ name: "C", total: 777 }
]
}) //=> [33, 123, 777]
Based on your comments on the answer from customcommander, I think you can write this fairly simply. I don't know how you receive your schema, but if you can turn the pathway to your lineItems node into an array of strings, then you can write a fairly simple function:
const lineItemTotal = compose (sum, pluck ('total'), path)
let order = {
path: {
to: {
lineItems: [
{name: "A", total: 33},
{name: "B", total: 123},
{name: "C", total: 777},
]
}
}
}
console .log (
lineItemTotal (['path', 'to', 'lineItems'], order)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {compose, sum, pluck, path} = R </script>
You can wrap curry around this and call the resulting function with lineItemTotal (['path', 'to', 'lineItems']) (order), potentially saving the intermediate function for reuse.
Is there a particular reason why you want to use lenses here? Don't get me wrong; lenses are nice but they don't seem to add much value in your case.
Ultimately this is what you try to accomplish (as far as I can tell):
map(prop('total'), order.lineItems)
you can refactor this a little bit with:
const get_total = compose(map(prop('total')), propOr([], 'lineItems'));
get_total(order);
You can use R.pluck to get an array of values from an array of objects:
const order = {"lineItems":[{"name":"A","total":33},{"name":"B","total":123},{"name":"C","total":777}]};
const result = R.pluck('total', order.lineItems);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

Kotlin how to split a list in to sublists

I would like to split a list into a few sublists, but I have no idea how to do it.
Once of my ideas was splitting the list by index of element. For exmaple "B" index is 0, "S" index 2, so I would like to take a part between index 0 - 1 into the first sublist, then the second sublist should be the part between index 2 - 5.
Example of my list:
val listOfObj = listOf("B", "B" , "S", "B", "B", "X", "S", "B", "B", "P")
Result after splitting:
listOf(listOf("B","B"), listOf("S", "B", "B", "X"), listOf("S", "B", "B", "P") )
How do I achieve such a result?
Here it goes. I wrote it from my phone without checking but the idea is basic.
val result = mutableListOf<List<String>>()
var current = mutableList<String>()
listOfObj.forEach { letter ->
if (letter == "S") {
result.add(current)
current = mutableListOf<String>()
}
current.add(letter)
}
if (current.isNotEmpty()) {
result.add(current)
}
You can even create an extension function for a List<T> that gets a separator element as a parameter and returns a list of lists.

Nitrogen get content of table

So, I have a nitrogen page, index.erl, which contains codes like this:
body() ->
[#table{
id = mytable,
rows=[
#tablerow{
cells=[#tableheader{text="column a"},
#tableheader{text="column b"},
#tableheader{text="column c"},
#tableheader{text="column d"}]
},
#custom_row{ %% just a wrapper around #tablerow
column_a = "a",
column_b = "b",
column_c = "c",
column_d = "d"
}
%% ... more #custom_rows omitted
]
},
#button{text="submit", postback=store_table}
].
event(store_table) ->
TableData = something_like_querySelector(mytable),
insert_into_database(TableData).
How do I get the content of mytable, does nitrogen has something like querySelector?
There isn't something as nice and clean as querySelector, but it is possible to retrieve the contents of an arbitrary DOM element though use of Nitrogen's #api{} action.
Using your code above, we could do the following:
body() ->
wf:wire(#api{name=send_table_contents, tag=some_tag}),
[#table{
id = mytable,
rows=[
#tablerow{
cells=[#tableheader{text="column a"},
#tableheader{text="column b"},
#tableheader{text="column c"},
#tableheader{text="column d"}]
},
#custom_row{ %% just a wrapper around #tablerow
column_a = "a",
column_b = "b",
column_c = "c",
column_d = "d"
}
%% ... more #custom_rows omitted
]
},
#button{text="submit", click="page.send_table_contents(objs('mytable').html())"}
].
api_event(send_table_contents, some_tag, [TableHTML]) ->
insert_into_database(TableHTML).
It's not as clean as being able to request the contents like you can with wf:q, but it does get the job done.
The quick explanation here is that the #api{} action creates a new function on the page called page.api_name_attribute (so if you look above, you'll see the name attribute was send_table_contents and the javascript function called in #button.click was also send_table_contents. The contents are then captured in an api_event(NameOfAPI, Tag, ListOfArgs) postback function.
That said, I've added this feature to the to-do list because it seems like a useful thing.