Immutable mergeIn overwrites the original values - immutable.js

I've got a problem when using Immutable.js with nested map and list, I was expected mergeIn will merge the new value with the old one, however it overwrite the value instead.
How to get it correctly?
const state = fromJS({
list: []
})
.update("list", l => l.push({ a: 1 }))
.mergeIn(["list", 0], { b: 3 })
.getIn(["list", 0])
I was expecting the final value is { a: 1, b: 3 }, however, the actual output is { b: 3 }

Immutable.js is not supposed to merge plain objects like that (prior to v4 anyway).
state.mergeIn(["list", 0], { b: 3 })
is equivalent to
state.updateIn(["list", 0], m => m.merge({ b: 3 }))
When the updater function of .updateIn() is called, since { a : 1} has no merge() method in its prototype, Immutable.js doesn't merge it but replaces with the new object instead.
You can fix this if you just make an Immutable.Map out of {a : 1}. Or use Immutable.js v4+: apparently, it uses Immutable.merge() to merge plain objects, exactly the way you expected it to work.

I tested it with immutableJS v4.0.0-rc.12 and it works as you expected, i.e. { a: 1, b: 3 }. So maybe you just have to update to that version

Related

Vega: transform array of values into accepted format

I'm using Vega for data visualization. Vega requires data which is shaped as an array of objects:
const accepted = [
{ num: 1, char: 'A' },
{ num: 2, char: 'B' },
{ num: 3, char: 'C' },
]
However, for sending data (e.g. via JSON), it is not efficient as the keys num and char are repeated multiple times. A more efficient way is sending the data as follows:
const efficient = {
num: [1, 2, 3 ],
char: ['A', 'B','C']
}
Right now I'm manually transforming the efficient structure above into the accepted structure before passing it into Vega. Is there any Vega transforms that I can use so taht I can pass efficient without having to transform it into accepted?
Use the flatten transform which should do what you need.
https://vega.github.io/vega/docs/transforms/flatten/
https://vega.github.io/vega-lite/docs/flatten.html

Karate : Matching data between nested array

Is there a way to match the response data from API which contain a nested array for a key where key-value pair are in different order inside the nested array in karate?
Scenario: Verify original data contains expected data
def original = [{ a:1, b: [{c:2},{d:3}]}]
def expected = [{ b: [{d:3},{c:2}], a:1 }]
Using contains deep method will solve the issue but I am expecting original data from a API response so in some point of time if one more field gets added to the API response, then my scenario will still get passed
Don't try to do everything in one-line. Split your matches, and there is more explanation in the docs:
* def inner = [{ c: 2 }, { d: 3 }]
* def response = [{ a: 1, b: [{ d: 3 }, { c: 2 }]}]
* match each response contains { b: '#(^^inner)' }
* match each response == { a: 1, b: '#(^^inner)' }
* match response[0] == { a: 1, b: '#(^^inner)' }
* match response == [{ a: 1, b: '#(^^inner)' }]
You don't need to use all of these, I'm showing the possible options.

Destructuring/list assignment with the `has` declarator

[I ran into the issues that prompted this question and my previous question at the same time, but decided the two questions deserve to be separate.]
The docs describe using destructuring assignment with my and our variables, but don't mention whether it can be used with has variables. But Raku is consistent enough that I decided to try, and it appears to work:
class C { has $.a; has $.b }
class D { has ($.a, $.b) }
C.new: :a<foo>; # OUTPUT: «C.new(a => "foo", b => Any)»
D.new: :a<foo>; # OUTPUT: «D.new(a => "foo", b => Any)»
However, this form seems to break attribute defaults:
class C { has $.a; has $.b = 42 }
class D { has ($.a, $.b = 42) }
C.new: :a<foo>; # OUTPUT: «C.new(a => "foo", b => 42)»
D.new: :a<foo>; # OUTPUT: «C.new(a => "foo", b => Any)»
Additionally, flipping the position of the default provides an error message that might provide some insight into what is going on (though not enough for me to understand if the above behavior is correct).
class D { has ($.a = 42, $.b) }
# OUTPUT:
===SORRY!=== Error while compiling:
Cannot put required parameter $.b after optional parameters
So, a few questions: is destructuring assignment even supposed to work with has? If so, is the behavior with default values correct/is there a way to assign default values when using destucturing assignment?
(I really hope that destructuring assignment is supported with has and can be made to work with default values; even though it might seem like a niche feature for someone using classes for true OO, it's very handy for someone writing more functional code who wants to use a class as a slightly-more-typesafe Hash with fixed keys. Being able to write things like class User { has (Str $.first-name, Str $.last-name, Int $.age) } is very helpful for that sort of code)
This is currently a known bug in Rakudo. The intended behavior is for has to support list assignment, which would make syntax very much like that shown in the question work.
I am not sure if the supported syntax will be:
class D { has ($.a, $.b = 42) }
D.new: :a<foo>; # OUTPUT: «D.new(a => "foo", b => 42)»
or
class D { has ($.a, $.b) = (Any, 42) }
D.new: :a<foo>; # OUTPUT: «D.new(a => "foo", b => 42)»
but, either way, there will be a way to use a single has to declare multiple attributes while also providing default values for those attributes.
The current expectation is that this bug will get resolved sometime after the RakuAST branch is merged.

How do I remove a key from an element object property

I have a Polymer 1.0 custom element which has a property called obj which is an object, say
obj = { a: 1,
b: 2}
How do I remove one of the keys?
I have tried this.set('obj.a', undefined)
and this.set('obj.a', null)
but result is {a: null (or undefined),
b: 2}
where what I want is just to remove 'a' leaving {b:2}
is there a correct way of doing it?
Use delete. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
Example:
let x = {a: 1, b: 2, '#sss': 3};
delete x.a; // x is now {b: 2, '#sss': 3}
delete x['#sss']; // x is now {b: 2}

Counting occurrences of a list item from a list?

(See edit at the bottom of this post)
I'm making a program in Elixir that counts the types of HTML tags from a list of tags that I've already obtained. This means that the key should be the tag and the value should be the count.
e.g. in the following sample file
<html><head><body><sometag><sometag><sometag2><sometag>
My output should be something like the following:
html: 1
head: 1
body: 1
sometag: 3
sometag2: 1
Here is my code:
def tags(page) do
taglist = Regex.scan(~r/<[a-zA-Z0-9]+/, page)
dict = Map.new()
Enum.map(taglist, fn(x) ->
tag = String.to_atom(hd(x))
Map.put_new(dict, tag, 1)
end)
end
I know I should be probably using Enum.each instead but when I do that my dictionary ends up just being empty instead of incorrect.
With Enum.map, this is the output I receive:
iex(15)> A3.test
[%{"<html" => 1}, %{"<body" => 1}, %{"<p" => 1}, %{"<a" => 1}, %{"<p" => 1},
%{"<a" => 1}, %{"<p" => 1}, %{"<a" => 1}, %{"<p" => 1}, %{"<a" => 1}]
As you can see, there are duplicate entries and it's turned into a list of dictionaries. For now I'm not even trying to get the count working, so long as the dictionary doesn't duplicate entries (which is why the value is always just "1").
Thanks for any help.
EDIT: ------------------
Okay so I figured out that I need to use Enum.reduce
The following code produces the output I'm looking for (for now):
def tags(page) do
rawTagList = Regex.scan(~r/<[a-zA-Z0-9]+/, page)
tagList = Enum.map(rawTagList, fn(tag) -> String.to_atom(hd(tag)) end)
Enum.reduce(tagList, %{}, fn(tag, acc) ->
Map.put_new(acc, tag, 1)
end)
end
Output:
%{"<a": 1, "<body": 1, "<html": 1, "<p": 1}
Now I have to complete the challenge of actually counting the tags as I go...If anyone can offer any insight on that I'd be grateful!
First of all, it is not the best idea to parse html with regexes. See this question for more details (especially the accepted answer).
Secondly, you are trying to write imperative code in functional language (this is about first version of your code). Variables in Elixir are immutable. dict will always be an empty map. Enum.map takes a list and always returns new list of the same length with all elements transformed. Your transformation function takes an empty map and puts one key-value pair into it.
As a result you get a list with one element maps. The line:
Map.put_new(dict, tag, 1)
doesn't update dict in place, but creates new one using old one, which is empty. In your example it is exactly the same as:
%{tag => 1}
You have couple of options to do it differently. Closest approach would be to use Enum.reduce. It takes a list, an initial accumulator and a function elem, acc -> new_acc.
taglist
|> Enum.reduce(%{}, fn(tag, acc) -> Map.update(acc, tag, 1, &(&1 + 1)) end)
It looks a little bit complicated, because there are couple of nice syntactic sugars. taglist |> Enum.reduce(%{}, fun) is the same as Enum.reduce(taglist, %{}, fun). &(&1 + 1) is shorthand for fn(counter) -> counter + 1 end.
Map.update takes four arguments: a map to update, key to update, initial value if key doesn't exist and a function that does something with the key if it exists.
So, those two lines of code do this:
iterate over list Enum.reduce
starting with empty map %{}
take current element and map fn(tag, acc) and either:
if key doesn't exist insert 1
if it exists increment it by one &(&1 + 1)