How to use setIn with immutable.js List - immutable.js

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

Related

Iterating over a list in JSON using TypeScript

I'm having a problem iterating over my json in TypeScript. I'm having trouble with one specific json field, the tribe. For some reason I can't iterate over that one. In the debugger, I'm expecting the Orc to show up but instead I get a 0. Why is this? How do I iterate correctly over my tribe data?
// Maps a profession or tribe group name to a bucket of characters
let professionMap = new Map<string, Character[]>()
let tribeMap = new Map<string, Character[]>()
let herolistJson = require('./data/HeroList.json')
for (let hero of herolistJson){
// Certain characters can have more than one tribe
// !!!!! The trouble begins here, tribe is 0???
for (let tribe in hero.tribe){
let tribeBucket = tribeMap.get(tribe) as Character[]
// If the hero does not already exist in this tribe bucket, add it
if(tribeBucket.find(x => x.name == hero.name) === undefined )
{
tribeBucket.push(new Character(hero.name, hero.tribe, hero.profession, hero.cost))
}
}
}
My json file looks like this
[
{
"name": "Axe",
"tribe": ["Orc"],
"profession": "Warrior",
"cost": 1
},
{
"name": "Enchantress",
"tribe": ["Beast"],
"profession": "Druid",
"cost": 1
}
]
in iterates over the keys of an object, not the values. The keys of an array are its indices. If you use of instead, you'll use the newer iterator protocol and an Array's iterator provides values instead of keys.
for (let tribe of /* in */ hero.tribe) {
Note, that this won't work in IE 11, but will work in most other browsers as well many JS environments that are ES2015 compatible. kangax/compat has a partial list.
Change the "in" to "of" in second loop.

How to load variable length JSON arrays in Chapel?

I'm trying to load the Yummly Data which includes JSON formatted training data. Here is a sample of a single record:
{
"id": 10259,
"cuisine": "greek",
"ingredients": [
"romaine lettuce",
"black olives",
"grape tomatoes",
"garlic",
"pepper",
"purple onion",
"seasoning",
"garbanzo beans",
"feta cheese crumbles"
]
}
And here is my attempt to load this data
use IO;
const test_data_f: string = "/home/buddha314/datasets/yummly/test.json",
train_data_f:string = "single_recipe.json";
writeln("let's load some json, shall we?");
record Recipe {
var cuisine: string,
id: int,
ingredients: [1..1] string;
}
var f = open(train_data_f, iomode.r);
var r = f.reader();
var final : Recipe;
r.readf("%jt\n", final);
writeln(final);
I clearly won't know the number of ingredients a priori, so I tried the line ingredients: [1..1] string; to no avail. After messing around with it, I couldn't get it to work.
Using a 'list' should work:
http://chapel.cray.com/docs/1.15/modules/standard/List.html
var ingredients : list(string);

Introducing Immutable.js into redux/react code

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"]

Dynamic ng-Grid with JSON data in angularJS?

I want to make a dynamic ng-grid , which adjusts its columns according to the key values in my JSON object. JSON object is fetched from an api. the problem I am facing is defining columns at runtime i.e The columns are not available at design time but will only be available only at runtime. I want to have something like :
http://plnkr.co/edit/q1Ye10OsIn9NOJmrICyD?p=preview
So that, I have as many columns as keys in my Json object. API's can vary so I need to make a grid which adjusts its columns.
My plunker is not working, but I hope it gives you idea, what I am trying to do.
Unless I'm misunderstanding what you want, you don't need to mess with columnDefines. Just having this:
faculty.controller('facultycontroller', function facultycontroller($scope, $http, $window){
$scope.facdata = [];
$scope.gridOptions = {
data: 'facdata'
};
$http.get("http://mtapi.azurewebsites.net/api/institute").then(function (result) {
$scope.facdata = result.data;
console.log($scope.facdata[0]);
});
});
will create the grid with a column for each key in your json.
Update
If you want to filter out any columns that begin with '$', you can do something like this:
angular.forEach(result.data[0], function(value, key){
if(key.indexOf('$') != 0)
$scope.columnDefines.push({ field: key, displayName: key});
});
Actually, you were close with what you were trying to do. You just need to put the columnDefines variable on $scope, and assign it to the gridOptions using a string, like this:
$scope.columnDefines = [];
$scope.gridOptions = {
data: 'facdata',
columnDefs: 'columnDefines'
};
Plunker
Try attaching your columnDefines variable to the scope ($scope.columnDefines). Then in your options do this:
$scope.gridOptions =
{
data: 'facdata',
columnDefs: 'columnDefines' //Note the quotes
};
This will make ng-grid watch your columnDefs for changes

How can I populate a form using hierarchical JSON data

I have a form that I need to populate with JSON data. The form contains select, textarea, and input elements that need to be populated. The JSON data is complex / hierarchical (i.e. many nested objects).
I am aware of http://www.keyframesandcode.com/code/development/javascript/jquery-populate-plugin/ but it uses square bracket notation to map to field names (e.g.
<input name="person[name][last]" ...
I need to use dot notation though (e.g.
<input name="person.name.last" ...
I'm using jQuery so a jQuery solution is fine. Thanks.
Here's a hacked together alternative to populate using a recursive function:
function populator(json, nodes){
$.each(json, function(key, value){
newNodes = nodes ? nodes.slice() : [];
newNodes.push(key);
if (typeof(value)=="object") {
populator(value, newNodes);
else
$('name["' + newNodes.join('.') + '"]').val(value);
}
});
}
With this you can do:
populator({
person: {
name: {
last: 'Doe',
first: 'John'
},
address: {
street: '123 Main Street',
city: 'Montgomery',
state: 'AL'
}
});