RamdaJS How to use R.find with R.or? - ramda.js

I'm still cutting my teeth on ramda and struggling with the basics.
I want to find the first object that has any of many properties set. So I'm trying to use a find with an or, but no matter how I construct it I cannot seem get it to work. repl.it
var xs = [{a: 1}, {b: 2}, {a: 3}];
R.find(R.or(R.prop('c'), R.prop('b')))(xs);
I was expecting this to evaluate to {b:2} but it keeps returning undefined. What am I doing wrong here?

In this case you will want R.either which takes two boolean producing functions, while R.or is just expecting two boolean values to compare (effectively a curried form of (a, b) => a || b).

I would not use prop to test whether an object has a property as it would return a false negative if a property is set to a falsy value. (Use has instead.) Also if you have more than two conditions you may want to consider using anyPass instead of either.
const findObject =
R.find(R.__, [
{a: 0},
{b: 1},
{c: 1}]);
// probably not the result you expected
findObject(
R.anyPass([
R.prop('a'),
R.prop('b')])); //=> {b: 1}
// most likely the result you expected
findObject(
R.anyPass([
R.has('a'),
R.has('b')])); //=> {a: 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

Related

Array assertion without knowing the position of the object

I am making a post call and after post call the object goes into array at random position so how can I assert for that object.without knowing it's response. message[position?].
Please suggest me what can I do.
Use JsonPath. Here is one example: https://stackoverflow.com/a/64373344/143475
Keep in mind there are plenty of ways to extract data from JSON that ignores the exact path or position. For example:
* def response = { a: 1, b: 2, c: 3, d: { a: 1, b: 2, e: 5 } }
* def extracted = $..e
* match extracted contains 5
If you are just concerned about arrays, use contains: https://github.com/karatelabs/karate#match-contains

Why does R.all with R.both does not equal R.allPass with the same arguments?

I'm just learning while doing ramda.js. Well, there are many ways to reach a goal with ramda, but there is on thing I do not understand.
I would like to check the input for an array of strings that all match one regular expression. I thought I could do it R.all(R.both(isString, isRegExp)), but it seems to deliver a true when the input is a number.
As expected R.allPass([isString, isRegExp]) gives a false with a number input.
But can anyone please explain me why R.all is returning a true? Or what and where is mistake (in thinking)?
Complete code:
var isString = R.is(String),
isMyRegExp = R.test(/^[a-z]+$/),
isMyRegExpString = R.both(isString, isMyRegExp),
isArrayOfMyRegExpStrings = R.all(isMyRegExpString),
isArrayOfMyRegExpStringsPass = R.allPass([isString, isMyRegExp]),
result = {
'all': isArrayOfMyRegExpStrings(9),
'allPass': isArrayOfMyRegExpStringsPass(9)
};
console.log(result);
// {
// all: true,
// allPass: false
// }
https://codepen.io/Eisenhardt/pen/PKLZqj
PS:
I know that I could shorten conditions with just the regexp, but there could be other situations where I need both conditions to be true. eg. isArrayOfNumber and sumOfNumbersOver50.
The second argument to R.all is expecting a list of values to test. Due to the way the function is implemented it is treating the 9 in your example as an empty list, resulting in a vacuous truth and evaluating to true.

What is the opposite of _.remove

_.remove($scope.posts, post);
I', using _.remove to remove items from an array using lodash. But how do I add objects again? So what is the opposite of _.remove.
_.remove removes an item from an array, now since you want an opposite of the remove which can be push, there is no _.push available. So, i think it's better to use native push function.
here are few things you can consider:
var posts = [{a:1},{b:3},{f:3}];
var post = {a:1};
_.remove(posts, post); // posts = [{b:3},{f:3}]
to add object at 0 index
posts.unshift(post);//posts = [{a:1},{b:3},{f:3}]
to add object at last index
posts.push(post);//posts = [{b:3},{f:3},{a:1}]
to insert object at an index
posts.splice(1, 0, {g:8}); // posts = [{a:1},{g:8},{b:3},{f:3}]
and you can use _.mixin of course.
_.mixin({
push: function(arr,obj){
return arr.push(obj);
}
});
and you can use it like
_.push(posts,post);
JsFiddle for mixin example
Please try _.fill, fills elements of array with value from start up to
_.fill(array, value, [start=0], [end=array.length])
_.fill([4, 6, 8, 10], '*', 1, 3);
// → [4, '*', '*', 10]

How to iterate over a map created in MVEL

I have created a map in MVEL and I have to iterate over it using foreach. How would I do that?
There is a similar question:
How to iterate over a map in mvel
But in that case the map was created in Java and had a method to return array of keys (entrySet) which is not the case with me.
//MVEL
map = [
'a': 'a1',
'b': 'b2',
'c': 'c3'
];
foreach (key: map) {
System.out.println(key);
}
I have tried both map and map.entrySet in the foreach loop but none seems to work.
Note: I test it using MVEL command line and using MVEL version 2.2.0.15
Although you have accepted an answer, I think it is better to add something as not to mislead other people:
... had a method to return array of keys (entrySet) which is not the case with me
First, Map is a Map. Map created in MVEL is simply a "Java" Map. The way to iterate is just the same and they are providing same methods
Second, entrySet() is not returning "array of keys". It is returning a Set of Entry (as its name suggests).
I am not sure why you cannot use entrySet as it works just fine for me. I suspect you have do foreach (e : map.entrySet). That will not work, because in MVEL, property navigation can mean several thing, like bean properties (which means it will call map.getEntrySet()), or looking up a map (which means it will call map.get('entrySet')), or getting the field (which means 'map.entrySet'). However all these are not valid for your case. You simply want to invoke map.entrySet() method so that you should just do foreach (e : map.entrySet())
The proper way to do is something like this:
map = ['a':'a1', 'b':'b1'] ;
foreach(entry : map.entrySet()) {
System.out.println('key ' + entry.key + ' value ' + entry.value)
};
You can use something like this:
map = [
'a': 'a1',
'b': 'b2',
'c': 'c3'
];
foreach (key : map.keySet()) {
System.out.println("Key:" + key + " Value:" + map[key]);
}
It outputs:
Key:b Value:b2
Key:c Value:c3
Key:a Value:a1

Specify local Dynamic in Grid

I would like to update specific parts of a Grid dynamically in different ways. Consider the following toy example: I have two rows: one must be updated one-by-one (a, b, c), as these symbols depend on different triggers; the second row depends on one single trigger (show) that allows displaying/hiding some data.
Now I know that I can wrap the whole Grid structure into Dynamic, and even specify which symbols to track, thus this example does what I want:
Checkbox[Dynamic[show]]
test = {0, 0};
Dynamic[Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
If[show, Prepend[test, "test:"], {}]}, Frame -> All],
TrackedSymbols :> {show}]
Though for certain reasons I would like to have a locally specified Dynamic, that is only applied to the second row of the Grid.
For those who are wondering what ungodly situation would it be, just imagine the followings: show is used in any of a, b or c, and these I do NOT want to update when show is changing, their changes depend on other triggers. Why not remove then show from the symbols of the first row? Imagine, I can't, as show is present in a function that is used in a, b or c, and this function I cannot access easily.
Of course wrapping the first argument of If into Dynamic won't help here, as the Grid itself or any of its cells won't become dynamic:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
If[Dynamic#show, Prepend[test, "test:"], {}]
}, Frame -> All]
Furthermore, wrapping a row into Dynamic makes the given row invalid, as it does not have head List anymore:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic#If[show, Prepend[test, "test:"], {}]
}, Frame -> All]
Mapping Dynamic over the row does not work either because show is not updated dynamically:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic /# If[show, Prepend[test, "test:"], {}]
}, Frame -> All]
Also, wrapping Dynamic[If[...]] around list members work, but now I have to evaluate If 3 times instead of just 1.
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
Dynamic[If[show, #, ""]] & /# Prepend[test, "test:"]
}, Frame -> All]
Would like to know if there is any solution to overcome this particular problem by locally applying a Dynamic wrapper on a row.
Here is a solution using the Experimental ValueFunction
show = True;
test = {0, 0};
Checkbox[Dynamic[show]]
Now write your own little Dynamic update function on the side
Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {}];
ValueFunction[show] = updateRow;
Now make the Grid, and now can use Dynamic on EACH row, not around the whole Grid, which is what you wanted:
Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#row}
},
Frame -> All
]
ps. I just read a post here by telefunkenvf14 that mentions this package and this function, which I did not know about, and when I saw this function, I remembered this question, and I thought it should be possible to use that function to solve this problem.
ps. I need to work more on placing the grid row correctly....
update(1)
I can't figure how to splice the final row over the columns in the grid. Which is strange, as it has List head, yet it won't go across all the columns. It will only go in the first cell. Tried Sequence, SpanFromLeft, and such, but no luck. May be someone can figure this part out.
Here is my current trial:
Needs["Experimental`"];
row = {};
updateRow[x_, v_] := row = If[v, {"test:", 0, 0}, {}];
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]
f = Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
List#Dynamic[row]
},
Frame -> All
]
It seems it should be doable. I do not see what is the problem now...
update(2)
As a temporary solution, I split the second row by force before hand. This made it possible to do what I want. Not sure if this meets the OP specifications or not (my guess is that it does not), but here it is:
Needs["Experimental`"];
ra = 0;
rb = 0;
rc = 0;
updateRow[x_, v_] :=
row = If[v, ra = "test:"; rb = 0; rc = 0, ra = ""; rb = ""; rc = ""]
ValueFunction[show] = updateRow;
show = False;
Checkbox[Dynamic[show]]
f = Grid[{
{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#ra, Dynamic#rb, Dynamic#rc}
},
Frame -> All]
This is actually a comment on #Nasser's solution and suggested fix to avoid manual splitting of the second row, but because of space limitations in the comment area, I post it as answer. Will be happy to delete it as soon as Nasser confirms that it works and incorporates it into his answer.
The clue to a solution is found in the Possible Issues section of Item in the documentation:
If Item is not the top-most item in the child of a function that supports Item, it will not work.
I use this to modify #Nasser's solution in the following way. First, I need to change the definition of row so that for both values of show the length of row is the same.
Needs["Experimental`"];
row = {"", "", ""};
updateRow[x_, v_] := row = If[v, Prepend[test, "test:"], {"", "", ""}];
Experimental`ValueFunction[show] = updateRow;
The second change needed is to wrap each element of Dynamic#row with Item:
Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
{Item[Dynamic#row[[1]]], Item[Dynamic#row[[2]]],
Item[Dynamic#row[[3]]]}}, Frame -> All]
Edit: Item wrapper is not really needed; it works just as well without it:
Grid[{{Dynamic#a, Dynamic#b, Dynamic#c},
{Dynamic#row[[1]], Dynamic#row[[2]],
Dynamic#row[[3]]}}, Frame -> All]