Introducing Immutable.js into redux/react code - immutable.js

I'm introducing Immutable.js into my redux/react project. I'm changing the likes of:
let {id, name} = user;
to:
let id = user.get('id');
let name = user.get('name');
That's twice as much code. Is there any way of coding the latter in a more concise manner?

You can not use destructuring with an Immutable.js Map, at least not right out of the box. If your project uses Babel, you can add a plugin called babel-plugin-extensible-destructuring.
After configuring that, you'll be able to use destructuring and something like this will work:
import {fromJS} from 'immutable';
const map = fromJS({author: {name: {first: "John", last: "Doe"}, birthdate: "10-10-2010"}});
const {author: {name: {first, last}, birthdate}} = map;
Also, note that something like List is an iterable and therefore can be destructured like a regular array.
For example:
const list = List(['Hello', 'World', 'This', 'Is', 'a', 'List']);
const [first, second, ...theRest] = list;
console.log(first);
> "Hello"
console.log(second);
> "World"
console.log(theRest);
> ["This", "Is", "a", "List"]

Related

JSON.stringify add a carriage return

I am using postman for batch API calls and want a new line between each records (for the ease of others copy and pasting into csv/excel)
let responses = pm.collectionVariables.get('collectionResponses')
if(responses) {
responses = JSON.parse(responses);
} else {
responses = []
}
responses.push(pm.response.json());
pm.collectionVariables.set('collectionResponses', JSON.stringify(responses));
I tried
JSON.stringify(responses, '},', '},\n')
and that did not work
This is what the output looks like
{"success":true,"data":"0.5950391865600001\t0.49508964727322147\t193.383783","id":"2ec0a50f-862e-11ec-a41f-06c185e97372"},
{"success":true,"data":"0.5950391865600001\t0.49508964727322147","id":"410113f9-8630-11ec-a41f-06c185e97372"},
The simplest, most reliable way of doing this is to stringify each array element individually rather than all together:
const json = theArray.map(el => JSON.stringify(el)).join(",\n");
Live Example:
const theArray = [
{id: 1},
{id: 2,},
{id: 3},
];
const json = theArray.map(el => JSON.stringify(el)).join(",\n");
console.log(json);
I've left off the [] there because you seemed not to want them, but of course you could add them (`"[" + theArray.map(/.../) + "\n]").
Although JSON.stringify accepts a third parameter you can use for indentation (which triggers pretty-printing), it's awkard to use it for this purpose. You could provide a single space and then replace "\n " since a literal newline won't appear within a JSON value:
const json = JSON.stringify([1, 2, 3], null, 1)
.replace(/\n /g, "\n");
console.log(json);
...but it's a bit hacky.

import and use d3.parseCsv version 5

I'm trying to use d3.csv.parse(string) as documented https://d3-wiki.readthedocs.io/zh_CN/master/CSV/#parse
I've installed "d3": "5.12.0" but I find that with
import * as d3 from "d3";
d3.csv.parse
is undefined. What version of d3 do those docs cover?
After some searching I find https://github.com/d3/d3-dsv and d3.csvParse but this doesn't work as I'm expecting.
const c = "Name,Count,Total Area\nFoo,6.0,0.13\nBar,8.0,0.24"
d3.csvParse(c, data => console.log(data))
I was expecting an array of objects, but instead I just get the first object
{Count: "6.0", Name: "Foo", Total Area: "0.13"}
Any ideas what I'm doing wrong here,
Thanks.
OK, so it seems that d3.csvParse() doesn't behave like d3.csv() and the second function argument is not a callback
https://github.com/d3/d3-dsv/blob/v1.1.1/README.md#dsv_parse
console.log( d3.csvParse(c))
[0: {Name: "Foo", Count: "6.0", Total Area: "0.13"}
1: {Name: "Bar", Count: "8.0", Total Area: "0.24"}]
Sorry for the noise!

NodeJS: Adding new child nodes to JSON Object

lets say there is customer object, i need to add new element address to this json object customer. how can I achieve this?
Both of these are not altering the customer JSON object
customer['address'] = addressObj
customer.address = addressObj
and I can not use push() as this is not adding a new item in list of objects.
Thanks,
Naren
Maybe your addressObj is not properly formed.
This works for me:
var customer = {"name": "Naren"};
customer.address1 = "stackoverflow";
customer.address2 = {"fulladdress":"stackoverflow"};
JSON.stringify(customer)
Output:
"{"name":"Naren","address1":"stackoverflow","address2":{"fulladdress":"stackoverflow"}}"
Maybe I am not clear on what exactly you want to do but it sounds to me as if you want have a JSON and want to merge it with another JSON, creating just a JSON file.
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
You now want to add Supergirl (the new element) to Superman (the old element) I assume. Take a look here # merge-json a simple package which does its job well. You would code as follows:
use strict;
var mergeJSON = require("merge-json");
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
let Json6 = mergeJSON(Json1,Json2);
Json6=mergeJSON(Json6,Json3);
You would end up with as follows:
Json6 = {'Superman': 'Favorite', 'Supergirl': 'Greatest', 'IronFist': 'Top 10'}
This is how I make use of combining JSON information or text information into a JSON file. You can get much more sophisticated with the module mentioned above. (Just do not confuse merge-json with json-merge and other modules.)
If this is not what you are looking for my apologies, then I did not understand the question correctly.

How to use setIn with immutable.js List

Ok I've got a list of objects, pretty standard.
const list = Immutable.List([{type:'thang',data:{id:'pants'}}]);
Now I want to change pants to shorts... so I'm thinking
list.setIn([0,'data','id'],'shorts');
Alas
Error: invalid keyPath
How is this done?
I can't even get this far despite messing around with this for a while :/ Once I know how to do this I'd like to know how to add a new element at a position
list.setIn([0,'data','length'],'short');
To add a new length attribute to the data object at position 0 in the list.
My bad. I was going wrong with the creation of the Immutable structure. If I change
const list = Immutable.List([{type:'thang',data:{id:'pants'}}]);
To
const list = Immutable.fromJS([{type:'thang',data:{id:'pants'}}]);
Then I can
list.setIn([0,'data','id'],'shorts');
Our nested structured data:
const state = {
Persons: [
{
fname: 'J.R.R',
lname: 'Tolkin',
},
{
fname: 'jack',
lname: 'London',
}
]
};
Requiring Immutable
const { fromJS } = require('immutable')
Turning simple object to Map
const stateMapped = fromJS(state);
Getting Data from nested structure
console.log(stateMapped.getIn(['Persons', 0, 'fname']))//output: J.R.R
setting data in nested structure
var objClone = stateMapped.setIn(['Persons', '0', 'fname'], 'John Ronald Reuel');
console.log('' + objClone.getIn(['Persons', 0, 'fname'])); //output: John Ronald Reuel

Regular expression to extract a JSON array

I'm trying to use a PCRE regular expression to extract some JSON. I'm using a version of MariaDB which does not have JSON functions but does have REGEX functions.
My string is:
{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}
I want to grab the contents of category. I'd like a matching group that contains 2 items, Jebb and Bush (or however many items are in the array).
I've tried this pattern but it only matches the first occurrence: /(?<=category":\[).([^"]*).*?(?=\])/g
Does this match your needs? It should match the category array regardless of its size.
"category":(\[.*?\])
regex101 example
JSON not a regular language. Since it allows arbitrary embedding of balanced delimiters, it must be at least context-free.
For example, consider an array of arrays of arrays:
[ [ [ 1, 2], [2, 3] ] , [ [ 3, 4], [ 4, 5] ] ]
Clearly you couldn't parse that with true regular expressions.
See This Topic:
Regex for parsing single key: values out of JSON in Javascript
Maybe Helpful for you.
Using a set of non-capturing group you can extract a predefined json array
regex answer: (?:\"category\":)(?:\[)(.*)(?:\"\])
That expression extract "category":["Jebb","Bush"], so access the first group
to extract the array, sample java code:
Pattern pattern = Pattern.compile("(?:\"category\":)(?:\\[)(.*)(?:\"\\])");
String body = "{\"device_types\":[\"smartphone\"],\"isps\":[\"a\",\"B\"],\"network_types\":[],\"countries\":[],\"category\":[\"Jebb\",\"Bush\"],\"carriers\":[],\"exclude_carriers\":[]}";
Matcher matcher = pattern.matcher(body);
assertThat(matcher.find(), is(true));
String[] categories = matcher.group(1).replaceAll("\"","").split(",");
assertThat(categories.length, is(2));
assertThat(categories[0], is("Jebb"));
assertThat(categories[1], is("Bush"));
There are many ways. One sloppy way to do it is /([A-Z])\w+/g
Please try it on your console like
var data = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}',
res = [];
data.match(/([A-Z])\w+/g); // ["Jebb", "Bush"]
OK the above was pretty sloppy however a solid single regex solution to extract every single element regardless of the number, one by one and to place them in an array (res) is the following...
var rex = /[",]+(\w*)(?=[",\w]*"],"carriers)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
arr = [],
res = [];
while ((arr = rex.exec(str)) !== null) {
res.push(arr[1]); // <- ["Jebb", "Bush", "Donald", "Trump"]
}
Check it out # http://regexr.com/3d4ee
OK lets do it. I have come up with a devilish idea. If JS had look-behinds this could have been done simply by reversing the applied logic in the previous example where i had used a look-forward. Alas, there aren't... So i decided to turn the world the other way around. Check this out.
String.prototype.reverse = function(){
return this.split("").reverse().join("");
};
var rex = /[",]+(\w*)(?=[",\w]*"\[:"yrogetac)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
rev = str.reverse();
arr = [],
res = [];
while ((arr = rex.exec(rev)) !== null) {
res.push(arr[1].reverse()); // <- ["Trump", "Donald", "Bush", "Jebb"]
}
res.reverse(); // <- ["Jebb", "Bush", "Donald", "Trump"]
Just use your console to confirm.
In c++ you can do it like this
bool foundmatch = false;
try {
std::regex re("\"([a-zA-Z]+)\"*.:*.\\[[^\\]\r\n]+\\]");
foundmatch = std::regex_search(subject, re);
} catch (std::regex_error& e) {
// Syntax error in the regular expression
}
If the number of items in the array is limited (and manageable), you could define it with a finite number of optional items. Like this one with a maximum of 5 items:
"category":\["([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)")?)?)?)?
regex101 example here.
Regards.