Please how do i achieve the following using ramda - functional-programming

I have a random array of numbers 1 to five occurring in ramdom sometimes [1,1,1,1,2,2] etc. I am tasked with finding the value with highest occurrence all the the time regardless. I achieved that in javascript like below using a library called ramda here . After reading the documentation, i went with a solution like below.
// filter out duplication in array that way you can get the uniq represented numbers
const uniqueItems = R.uniq(params);
// use the unique numbers as keys and create a new array of object
const mappedItemsWithRepresentations = map((a) => ({ color: a, rep: params.filter(b => b === a).length }), uniqueItems);
// and then finally, select the item with highest rep and return it key
const maxRepItem = mappedItemsWithRepresentations.reduce((acc, curr) => acc.rep > curr.rep ? acc : curr, []);
return maxRepItem.key; // gives me the correct value i need
However, reading through more in the documentation and going through the example here, i realised there is a way i can combine the logic above and simply with ramda. I tried numerous attempt possible and the closest i could get are below.
const getMaxRep = curry(pipe(uniq, map((a) => ({ color: a, rep: filter(b => b === a).length })), pipe(max(pathEq("rep")), tap(console.log))));
console.log("Max Rep here", getMaxRep(params));
I also tried utilising the reduced feature here, all to no avail. Please how do i arrange achieve that ? Any help will be appreciated.

Ramda has R.countBy to get the number of occurrences. You can convert the resulting object of country to pairs [value, count], and then reduce it to find the pair with the highest count:
const { pipe, countBy, identity, toPairs, reduce, maxBy, last, head } = R
const fn = pipe(
countBy(identity), // count the occurrences
toPairs, // convert to pairs of [value, count]
reduce(maxBy(last), [0, 0]), // reduce to find the maximum occurrence
head, // get the actual value
Number, // convert back to an number
)
const arr = [1,1,1,1,2,2]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
A slight variation on this idea that collects values with the same count to an array. This will handle cases in which the frequency of several items is identical:
const { pipe, countBy, identity, toPairs, invert, reduce, maxBy, last, head, map } = R
const fn = pipe(
countBy(identity), // count the occurrences
invert, // combine all values with the same count
toPairs, // convert to pairs of [value, count]
reduce(maxBy(head), [0, 0]), // reduce to find the maximum occurrence
last, // get the actual values
map(Number), // convert back to numbers
)
const arr = [1,1,1,1,2,2,3,3,3,3]
const result = fn(arr)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

nice use case, try this:
const maxReduce = reduce(maxBy(last), [0,0])
const getMaxRep = pipe(countBy(identity), toPairs, maxReduce, head)
console.log(getMaxRep([1,1,1,1,2,2]))
countBy is a really nice start, sadly Ramda don't support reduce for object but we can convert to an array of arrays using toPairs function and finish the work.

It's not entirely clear to me what it is you're asking for.
But it might be something like this:
const maxRep = pipe (
countBy (identity),
toPairs,
map (zipObj(['color', 'rep'])),
reduce (maxBy (prop ('rep')), {rep: -Infinity}),
)
const params = [1, 2, 3, 4, 2, 3, 5, 2, 3, 2, 1, 1, 4, 5, 5, 3, 2, 5, 1, 5, 2]
console .log (
maxRep (params)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {pipe, countBy, identity, toPairs, map, zipObj, reduce, maxBy, prop} = R </script>
We start with a list of values drawn from {1, 2, 3, 4, 5}, occuring in some random, multiply-occuring order.
With countBy(identity) we change the original list into something like
{"1": 4, "2": 6, "3": 4, "4": 2, "5": 5}
with the counts associated with each entry.
toPairs formats that as an array like
[["1", 4], ["2", 6], ["3", 4], ["4", 2], ["5", 5]]
(You could also use Object.entries here.)
Then by calling map (zipObj (['color', 'rep'])), we turn this into
[{"color": "1", "rep": 4}, {"color": "2", "rep": 6}, ...]
Finally, we reduce the result, using maxBy (prop ('rep')), which chooses the one with the maximum rep value. For the initial value to the max call, we create a dummy object, {rep: -Infinity} that will compare less than any in your list.
If you wanted to also keep that final intermediate structure, you could rename that function to makeReps, dropping off the last function in the pipeline, and then making a new maxRep out of it.
Then you could call
const reps = makeResps (params)
const maxVal = maxRep (reps)
and use both.
But all this presupposes that the value with color and rep properties is what you need. If you just need the count then the other solutions already here handle that fine.

Related

Reclassify all pixel values in all of the images in an image collection - GEE

I am new to GEE so the answer to this question may be simple to most of you. I am looking for a way to reclassify pixel values in all of the images in an image collection. I'm working with the Monthly History data from the Global Surface Water dataset and targeting the months March-May. As it currently is, water pixels have a value of 2, non-water pixels are 1, and non-sampled pixels (no data) are 0. I would like to reclassify such that water = 1, not water = 0, and everything else is masked. My code is below:
var dataset = ee.ImageCollection('JRC/GSW1_2/MonthlyHistory')
.filterBounds(roi)
.map(function(image){return image.clip(roi)})
.filter(ee.Filter.calendarRange(3, 5, 'month'));
print(dataset);
This is the part that doesn't work...
var reclassified = function(img) {
return img.remap(([2, 1], [1, 0]), 'water');
};
var new_ds = dataset.map(reclassified)
print(new_ds);
You have an extra set of parentheses here:
return img.remap(([2, 1], [1, 0]), 'water');
^ ^
The effect of this mistake is to proceed as if you had written img.remap([1, 0], 'water'), which fails because 'water' can't be turned into a list.
There is another problem: when you're not using the named parameters form, you have to write all the arguments up to the last optional one you want to specify. The parameter list is remap(from, to, defaultValue, bandName), so you need to write a defaultValue even though you don't need it. In Earth Engine API calls, you can use null for any optional parameter you don't want to specify:
return img.remap([2, 1], [1, 0], null, 'water');
Or, you can use named arguments for the same result:
return img.remap({
from: [2, 1],
to: [1, 0],
bandName: 'water'
});
Or, since in this particular case your image contains only one band, you can leave out the bandName entirely:
return img.remap([2, 1], [1, 0]);

How to compose functions like zip-apply-ish

Assuming I have a bunch of functions of arity 2: f: a b -> x, g: c d -> y,
etc. up to unary function u: a -> a. What I would like to do is to chain them in such a way:
f(_, g(_, .... z(_, u(_))...)
where inside _ placeholders consecutive values from given input array will be injected. I'm trying to solve this using Ramda library.
Another, very similar problem I have is chaining the functions the same way but the _ placeholder being filled with the same value against which this composition is being executed.
To be more specific:
// 1st problem
someComposition( f(v[0], g(v[1], ..... z(v[n-1], u(v[n]))...) )(v);
// 2nd problem
someComposition2( f(v, g(v, ..... z(v, u(v))...) )(v);
Best what I could came up with for 2nd problem was, assuming all function are currable, following piece of code (hate it because of the (v) repetitions):
compose(
z(v),
...
g(v),
f(v),
u
)(v);
I tried solving it with compose, composeK, pipe, ap but none of them seem to applied to this situation or I just simply am not able to see the solution. Any help is more then welcome.
There's nothing directly built into Ramda for either of these. (Disclaimer: I'm one of the Ramda authors.) You can create composition functions like these, if you like, though:
const {tail, compose, reduce, identity, reverse} = R;
const f = (x, y) => `f(${x}, ${y})`;
const g = (x, y) => `g(${x}, ${y})`;
const h = (x, y) => `h(${x}, ${y})`;
const i = (x, y) => `i(${x}, ${y})`;
const j = (x) => `j(${x})`;
const multApply = (fns) => (...vals) => fns.length < 2
? fns[0].apply(null, vals)
: fns[0](vals[0], multApply(tail(fns))(...tail(vals)));
console.log(multApply([f, g, h, i, j])('a', 'b', 'c', 'd', 'e'));
//=> f(a, g(b, h(c, i(d, j(e)))))
const nest = compose(reduce((g, f) => (v) => f(v, g(v)), identity), reverse);
console.log(nest([f, g, h, i, j])('v')) //=> f(v, g(v, h(v, i(v, j(v)))));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
Neither of these does any error checking for empty lists, or for an arguments list shorter than the function list (in the first case.) But other than that, they seem to fit the bill.
There's sure to be a recursive version of the second one to match the first, but this implementation is already fairly simple. I didn't readily see a version of the first as simple as the second, but it might well exist.
There's probably some handy Ramda function that I don't know of, or some super functional combinator-thingy I don't understand that makes this easy, but anyway:
You could create your own composition function to compose a list of binary functions and inject values. This function takes a list of functions and a list of arguments. It partially applies the first function it gets to the first argument and keeps on doing so until it's out of arguments, at which it returns a final composed (unary) function:
// Utils
const { add, subtract, multiply, identity, compose, isNil } = R;
const square = x => x * x;
// Our own compose method
const comp2_1 = ([f2, ...f2s ], [x, ...xs], f = identity) =>
isNil(x)
? compose(f2, f)
: comp2_1(f2s, xs, compose(f2(x), f));
// An example
const myFormula = comp2_1(
[add, subtract, multiply, square],
[10, 5, 2]);
// 3 + 10 = 13
// 13 - 5 = 8
// 8 * 2 = 16
// 16 * 16 = 256
console.log(myFormula(3));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>
This example will only work for xs.length === fs.length + 1. You might want it to be a bit more flexible by, for instance, continuing the composition even when we're out of arguments:
/* ... */
isNil(x)
? isNil(f2)
? f
: comp2_1(f2s, [], compose(f2, f))
: /* ... */

How do I infinitely repeat a sequence in Kotlin?

I want to infinitely repeat T elements in a Sequence<T>. This can't be done using kotlin.collections.asSequence. For example:
val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val many = 10
finiteIntSequence.take(many).forEach(::print)
// 123
This is not what I want. I expected some kind of kotlin.collections.repeat function to exist, but there isn't, so I implemented one myself (e.g. for this IntArray):
var i = 0
val infiniteIntSequence = generateSequence { intArray[i++ % intArray.size] }
infiniteIntSequence.take(many).forEach(::print)
// 1231231231
This is quite imperative, so I feel there must be a more functional and less verbose way to do this. If it exists, what is/are Kotlin's standard way(s) to repeat collections / arrays a(n) (in)finite amount of times?
Update: coroutines are no longer experimental as of Kotlin 1.3! Use them as much as you like :)
If you allow the use of coroutines you can do this in a pretty clean way using sequence:
an infinite amount of times
fun <T> Sequence<T>.repeat() = sequence { while (true) yieldAll(this#repeat) }
Note the use of a qualified this expression this#repeat - simply using this would refer to the lambda's receiver, a SequenceScope.
then you can do
val intArray = intArrayOf(1, 2, 3)
val finiteIntSequence = intArray.asSequence()
val infiniteIntSequence = finiteIntSequence.repeat()
println(infiniteIntSequence.take(10).toList())
// ^ [1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
a finite amount of times
fun <T> Sequence<T>.repeat(n: Int) = sequence { repeat(n) { yieldAll(this#repeat) } }
To avoid using the experimental coroutines, use:
generateSequence { setOf("foo", 'b', 'a', 'r') }
.flatten() // Put the Iterables' contents into one Sequence
.take(5) // Take 5 elements
.joinToString(", ")
// Result: "foo, b, a, r, foo"
or alternatively, if you want to repeat the entire collection a number of times, just take before flattening:
generateSequence { setOf("foo", 'b', 'a', 'r') }
.take(5) // Take the entire Iterable 5 times
.flatten() // Put the Iterables' contents into one Sequence
.joinToString(", ")
// Result: "foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r, foo, b, a, r"
For the original question's IntArray, the array first must be converted to an Iterable<Int> (otherwise flatten() isn't available):
val intArray = intArrayOf(1, 2, 3)
generateSequence { intArray.asIterable() }
.flatten()
.take(10)
.joinToString(", ")
// Result: "1, 2, 3, 1, 2, 3, 1, 2, 3, 1"
Furthermore, other types of Array, e.g. ByteArray or LongArray, as well as Map are not Iterable, but they all implement the asIterable() method like IntArray in the example above.
I think this is pretty clear:
generateSequence(0) { (it + 1) % intArray.size }
.map { intArray[it] }
.forEach { println(it) }
A generic solution would be to reuse the proposal from this answer with extension functions:
fun <T> Array<T>.asRepeatedSequence() =
generateSequence(0) {
(it + 1) % this.size
}.map(::get)
fun <T> List<T>.asRepeatedSequence() =
generateSequence(0) {
(it + 1) % this.size
}.map(::get)
Called like this:
intArray.asRepeatedSequence().forEach(::println)
I'm unsure if this is due to API changes in Kotlin, but it's possible to do the following:
fun <T> Sequence<T>.repeatForever() =
generateSequence(this) { it }.flatten()
Live example: https://pl.kotl.in/W-h1dnCFx
If you happen to have Guava on your classpath, you can do the following:
val intArray = intArrayOf(1, 2, 3)
val cyclingSequence = Iterators.cycle(intArray.asList()).asSequence()
// prints 1,2,3,1,2,3,1,2,3,1
println(cyclingSequence.take(10).joinToString(","))

Get value from array using any given t

What I am trying to accomplish, is to be able to put some values inside an array, then based on a t (0-1), get a value out of the array based on its stored values.
To make this more clear, here's an example:
Array values = [0, 10]
Now this array would return value 0 for t=1 and value 10 for t=1. So t=.3 will give a value of 3.
Another example:
Array values = [10, 5, 5, 35]
t=.25 will give a value of 5
t=.125 will give a value of 7.5
Im looking for the most efficient formula to get the value at any given t using a given array.
Currently I'm using this (pseudo code)
var t:Number = .25;
var values:Array = [10, 5, 5, 35];
if(t == 1) value = [values.length-1];
else
var offset:Number = 1/values.length;
var startIndex:int = int(t/offset);
var fraction:Number = t % offset;
var roundPart:Number = (values[startIndex+1] - values[startIndex]) * fraction;
var value:Number = values[startIndex] + roundPart;
But i'm sure there's a far more better way of doing this. So i'm calling for the mathematicians on here!
Here is a One Liner in Mathematica. It's doing the same thing you are, only slightly more compact.
Arrays indexes start at 1.
values = {10, 5, 5, 35, 0}
f[a_, x_] := a[[k = IntegerPart[(k1 = (Dimensions[a][[1]] - 2) x)] + 1]] +
FractionalPart[k1] (a[[k + 1]] - a[[k]])
So your interpolation result on:
In[198]:= f[values,1]
Out[198]= 35
Etc.
If you plot changing the x scale:

JavaFX: concatenating sequences

Is there a standard library function or built-in construct to concatenate two sequences in JavaFX?
Here a Sequences.concatenate() function is mentioned, but it is nowhere to be seen in the official API.
Of course one could iterate over each sequence, inserting the values into a new sequence e.g:
function concatenate(seqA: Object[], seqB: Object[]) : Object[] {
for(b in seqB) insert b into seqA;
seqA;
}
..but surely something as basic as concatenation is already defined for us somewhere..
It is very simple, since there cannot be sequence in sequence (it all gets flattened), you can do it like this:
var a = [1, 2];
var b = [3, 4];
// just insert one into another
insert b into a;
// a == [1, 2, 3, 4];
// or create a new seq
a = [b, a];
// a == [3, 4, 1, 2];
Hope that helps.

Resources