ramda set lensPath on array item changes array to object - ramda.js

const o = { a: [1,2,3] }
R.set(R.lensPath(['a',1]), 5, o)
the result is
{"a": {"0": 1, "1": 5, "2": 3}}
but it should be
{ a: [1,5,3] }
How do I get the correct result?

Related

Ramda - How to map object values to string

I am trying to use Ramda to get x,y coordinates to draw polyline in svg.
I have edge object which contains all the points I need and it looks like this:
const edge = {
"id": "e1_s0",
"startPoint": {
"x": 212,
"y": 505.33333333333326
},
"endPoint": {
"x": 232,
"y": 302
},
"bendPoints": [
{
"x": 222,
"y": 505.33333333333326
},
{
"x": 222,
"y": 302
}
],
"incomingShape": "n1",
"outgoingShape": "n2"
}
I tried to use Ramda to get x, y from startPoint, endPoint and bendPoints. I came up with this piece of code:
R.pipe(
R.pick(['bendPoints', 'endPoint', 'startPoint']),
R.values,
R.flatten,
R.sortBy(R.prop('x'))
)(edge)
Here you can check it in ramda editor
As a result, I get:
[
{
x: 212,
y: 505.33333333333326
},
{
x: 222,
y: 505.33333333333326
},
{
x: 222,
y: 302
},
{
x: 232,
y: 302
}
]
But I need a string with x and y pairs divided by space and I have no idea how to proceed to get to that point: 212,505.33333333333326 222,505.33333333333326 222,302 232,302
Any help would be appreciated
EDIT: complete solution
R.pipe(
R.pick(['bendPoints', 'endPoint', 'startPoint']),
R.values,
R.flatten,
R.sortBy(R.prop('x')),
R.map(
R.pipe(
R.props(['x', 'y']),
R.join(',')
)
),
R.join(" ")
)(edge)
I think the steps you need are:
For each point,
Take the x and y values, and
Join those in to a single string, separated by ","
Take those strings and join them in to a single string, separated by " "
Which can be translated to ramda quite literally:
const formatPoints = pipe(
map(
pipe(
props(["x", "y"]),
join(",")
)
),
join(" ")
);

Remove specific key and value from nested json array in PostgreSQL column

I have a json object field in PostgreSQL in mytable.fields as below
{
"a": "1",
"b": [
{
"c": 2,
"d": 3
},
{
"c": 4,
"d": 5
},
{
"c": 6,
"d": 7
}
]
}
How can I delete all "c" key and value pairs like as below?
I found other StackOverflow solutions that remove the whole object, but I couldn't find this.
{
"a": "1",
"b": [
{
"d": 3
},
{
"d": 5
},
{
"d": 7
}
]
}
with data as (
select
your_json_col :: jsonb as obj,
jsonb_array_elements((your_json_col ->> 'b') :: jsonb) :: jsonb - 'c' as new_obj
from your_table)
select
obj || jsonb_build_object('b', jsonb_agg(new_obj))
from data
group by obj;

Ramda - get array of objects using ids from other array

I have two sets of data and I would like to use the first one to get an array of objects from the second one. I tried to deal with it by myself but I am missing few steps.
Here is set of ids to use:
const idSet = {
"41": {
"id": "41"
},
"42": {
"id": "42"
},
"43": {
"id": "43"
}
}
And here is second set:
const nodes = {
"3": {
"nodeCommentId": 3,
"nodeId": 43,
},
"4": {
"nodeCommentId": 4,
"nodeId": 41
},
"6": {
"nodeCommentId": 6,
"nodeId": 42
},
"7": {
"nodeCommentId": 7,
"nodeId": 44
},
}
I need to search by id and nodeId so I tried to use something like this to get only ids from first set:
const ids = R.compose(
R.values(),
R.pluck('id')
)(idSet)
I also came up with something like: R.filter(R.compose(R.flip(R.contains)(ids), R.prop('nodeId')), nodes);
But then I have nodeId which is a number and not a string plus I need an array of objects without keys.
Desired output:
[
{
nodeCommentId: 3,
nodeId: 43
},
{
nodeCommentId: 4,
nodeId: 41
},
{
nodeCommentId: 6,
nodeId: 42
}
]
Any help will be appreciated.
This is probably too ugly to use, but it might be a start at a nice solution:
const nodesById = (idSet) => {
const ids = map (Number, pluck ('id') (values (idSet)))
return pipe (values, filter (pipe (prop('nodeId'), contains(__, ids))))
}
const idSet = {41: {id: "41"}, 42: {id: "42"}, 43: {id: "43"}}
const nodes = {3: {nodeCommentId: 3, nodeId: 43, }, 4: {nodeCommentId: 4, nodeId: 41}, 6: {nodeCommentId: 6, nodeId: 42}, 7: {nodeCommentId: 7, nodeId: 44}}
console .log (
nodesById (idSet) (nodes)
)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
<script>const {map, pluck, values, pipe, filter, prop, contains, __} = R </script>
I'm sure that with a little work, we could make this entirely point-free, but I doubt that will help readability.
Transform the idSet to an array of numbers, and then user R.innerJoin to get the items with the matching nodeId:
const { pipe, values, pluck, map, innerJoin, __, curry } = R
const getIds = pipe(values, pluck('id'), map(Number))
const getNodesById = curry((idSet, nodes) =>
pipe(
values,
innerJoin(
({ nodeId }, id) => nodeId === id,
__,
getIds(idSet)
)
)(nodes)
)
const idSet = {41: {id: "41"}, 42: {id: "42"}, 43: {id: "43"}}
const nodes = {3: {nodeCommentId: 3, nodeId: 43, }, 4: {nodeCommentId: 4, nodeId: 41}, 6: {nodeCommentId: 6, nodeId: 42}, 7: {nodeCommentId: 7, nodeId: 44}}
const result = getNodesById(idSet)(nodes)
console.log(result)
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>

Getting the maximum value from an array in a JSON response in Karate

I have the following Json as a response from a API call
{
"location": {
"name": "London",
"region": "City of London, Greater London",
"country": "United Kingdom",
"lat": 51.52,
"lon": -0.11,
"tz_id": "Europe/London",
"localtime_epoch": 1583594426,
"localtime": "2020-03-07 15:20"
},
"forecast": {
"forecastday": [
{
"date": "2020-03-03",
"day": {
"maxtemp_c": 9,
"mintemp_c": 4
}
},
{
"date": "2020-03-04",
"day": {
"maxtemp_c": 8,
"mintemp_c": 4.1
}
},
{
"date": "2020-03-05",
"day": {
"maxtemp_c": 7,
"mintemp_c": 5.6
}
}
]
}
}
I want to find out which date had the highest temperature amongst the 3 days.
The way I am currently doing feels inefficient as I am checking for the temperature element within my js function and it is as follows
* def hottest =
"""
function(array) {
var greatest;
var indexOfGreatest;
for (var i = 0; i < array.length; i++) {
if (!greatest || array[i].day.maxtemp_c > greatest) {
greatest = array[i].day.maxtemp_c;
indexOfGreatest = i;
}
}
return indexOfGreatest;
}
"""
* def index = call hottest response.forecast.forecastday
* def hottestdate = response.forecast.forecastday[index].date
* print hottestdate
With this I am getting the correct result but can someone kindly suggest a better way of doing this?
Best practice in Karate is to NOT use JS for loops at all. It results in cleaner, more readable code:
* def fun = function(x){ return { max: x.day.maxtemp_c, date: x.date } }
* def list = karate.map(response.forecast.forecastday, fun)
* def max = 0
* def index = 0
* def finder =
"""
function(x, i) {
var max = karate.get('max');
if (x.max > max) {
karate.set('max', x.max);
karate.set('index', i);
}
}
"""
* karate.forEach(list, finder)
* print 'found at index', index
* print 'item:', list[index]
Note how easy it is to re-shape a given JSON, the result of list here would be:
[
{
"max": 9,
"date": "2020-03-03"
},
{
"max": 8,
"date": "2020-03-04"
},
{
"max": 7,
"date": "2020-03-05"
}
]

Vue JS2 find array value by id

How can i get the value by id from a array in vue js? Many thanks with solution
list = [
{
"name": "Apple",
"id": 1,
},
{
"name": "Orange",
"id": 2,
}
]
watch: {
food: function (val) {
//Get food name by val(id)
}
}
Use Array.find method, which returns the value of the first element in the array that satisfies the provided testing function:
var food = list.find(food => food.id === val)
var name = food ? null : food.name
let list = [
{
"name": "Apple",
"id": 1,
},
{
"name": "Orange",
"id": 2,
}
]
console.log(
list.find(food => food.id === 1).name
)