Project data out of an immutable map to a different shape - immutable.js

I have a Map of immutable objects with a structure like:
id1: {
someField: 'anyvalue',
description: 'description1'
},
id2: {
someField: 'anotherValue`,
description: 'description2'
}
I want to project a List of the descriptions without resorting to toJS():
[ 'description1', 'description2' ]
How do I do this?

const data = new Immutable.Map({id1: {
someField: 'anyvalue',
description: 'description1'
},
id2: {
someField: 'anotherValue',
description: 'description2'
}});
const out = data.valueSeq().map(v => v.description).toList();
console.log(out)
<script src="https://cdnjs.cloudflare.com/ajax/libs/immutable/3.8.2/immutable.js"></script>

Related

How to map an object from JSON file to another object?

Here is my json file
{
"data": [
{
"firstName": "Tom",
"lastName": "Yoda",
"type": "guest",
"id": "0",
"gender": m,
"data": { "age": 26, "born": "UK" }
},
]
}
This data array could have more entries.
I have to map the values into an interface which looks like:
InterfacePerson {
id: string;
title: string;
firstName: string;
lastName: string;
age: string;
location: string;
}
I am unable to change the interface. So I'm trying to do some pseudo coding.
const list;
list = convertToInterfacePerson = (value): Array<InterfacePerson> => {
return {
id: value.id,
title: if(value.gender === "m")? "Mr" : "Mrs",
firstName: value.firstName,
lastName: value.lastName,
age: value.data.age,
//...
}
}
I think you were trying to use a conversion mapping function called convertToInterfacePerson but you hadn't set it up yet (separately from trying to use it). The code below shows it declared and used within a map Array method call. I believe this resolves the error(s) you were getting.
// Copied in the JSON for demonstration
const sourceJson = {
"data": [
{
"firstName": "Tom",
"lastName": "Yoda",
"type": "guest",
"id": "0",
"gender": "m",
"data": { "age": 26, "born": "UK" }
},
]
};
// Declared the InterfacePerson interface
interface InterfacePerson {
id: string;
title: string;
firstName: string;
lastName: string;
age: string;
location: string;
}
// Declared the conversion mapping function (optional parameter typing included)
const convertToInterfacePerson = (value: { firstName: string, lastName: string, type: string, id: string, gender: string, data: { age: number, born: string } }): InterfacePerson => {
return {
id: value.id,
// Removed the `if` statement due to ternary conditional
title: ((value.gender === "m") ? "Mr" : "Mrs"),
firstName: value.firstName,
lastName: value.lastName,
// Wrapped the value.data.age in a string conversion
age: String(value.data.age),
location: value.data.born
};
}
// Declared and assigned the list based on the returned array from the mapping function (each element is applied in the `convertToInterfacePerson` function)
const list = sourceJson.data.map(convertToInterfacePerson);
// Show the result of the conversion
console.log(JSON.stringify(list, null, 2));
And for a live example, check out this TypeScript Playground script containing this solution.

Mongoose: TypeError: Method Uint8Array.length called on incompatible receiver

I'm making a small website with i18n. When starting I used local json files, but after switching to mongodb I experience an error I don't understand. A good explanation is highly appreciated.
The error I get is this:
TypeError: Method Uint8Array.length called on incompatible receiver [object Object]
I structure i18n data with "da" and "en" properties. I then use a method for filtering relevant language.
Here are examples of my data, both json and corresponding mongoose result. Both copied from terminal (printed with console.log):
json
[ { lang: { da: 'Dansk', en: 'Danish' }, rating: 5 },
{ lang: { da: 'Engelsk', en: 'English' }, rating: 5 },
{ lang: { da: 'Tysk', en: 'German' }, rating: 5 } ]
mongoose
[ { _id: 57e2561369e4bc0a8ca6c630,
lang: { da: 'Dansk', en: 'Danish' },
rating: 5,
id: '57e2561369e4bc0a8ca6c630' },
{ _id: 57e2561369e4bc0a8ca6c631,
lang: { da: 'Engelsk', en: 'English' },
rating: 5,
id: '57e2561369e4bc0a8ca6c631' },
{ _id: 57e2561369e4bc0a8ca6c632,
lang: { da: 'Tysk', en: 'German' },
rating: 5,
id: '57e2561369e4bc0a8ca6c632' } ]
filterLanguage method
var traverse = require('traverse');
var filterLanguage = function(language, obj) {
return traverse(obj).map(function (item) {
if (this.key === language) {
this.parent.update(item);
}
});
};
So filterLanguage('da', languages); should return something like:
[ { lang: 'Dansk', rating: 5 },
{ lang: 'Engelsk', rating: 5 },
{ lang: 'Tysk', rating: 5 } ]
filterLanguage() works on a local, valid JSON file but not on the Mongoose result set...
I tried JSON.stringify(obj). I also tried setting toObject() method in Mongoose models but no luck.
What am I doing wrong and how can I fix it?
--------- EDIT ---------
Model
var mongoose = require('mongoose');
var languageSchema = mongoose.Schema({
local: {
lang: { da: String, en: String },
rating: Number
}
});
module.exports = mongoose.model('Language', languageSchema);
Query
language.find({}, function(err, results) {
var obj = filterLanguage(lang, results.languages);
console.log(obj);
});
I tried setting toObject on the schema like this:
languageSchema.set('toObject', { virtuals: true });
The error you get is related to traverse not being able to handle ObjectId instances in your results array.
Since it looks like you don't use _id or id, the easiest way to fix this is to exclude those properties from the result documents:
language.find({}, '-_id -id', function(err, results) { ... })
(-id is probably superfluous, because it's a virtual that depends on _id)

Getting json object data with react

I am attempting to pull data out of json like this, which is imported as "values"
{
"content": {
"person": [
{
"name": "Test"
"age" : "24:
}
]
}
}
I am using .map like below but getting the error .default.map is not a function I believe it is because i have objects not arrays, i've tried a bunch of stuff including object.keys but i'm getting errors all over the place, any direction would be appreciated.
import values from './sample.json'
const vals = values.map((myval, index) => {
const items = person.items.map((item, i) => {
return (
<div>{item.name}</div>
)
})
return (
<div>{items}</div>
)
})
I think your data and code have some errors. But after fixing those and also changing the name from 'person' to 'people' if that's what you are after, here's the code that does what you are trying to do:
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
},
};
var App = React.createClass({
render: function () {
var people = data.content.people.map(function (person) {
return <div>{person.name}</div>;
});
return <div>{people}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the JSBin for that: https://jsbin.com/coyalec/2/edit?html,js,output
Update: I'm updating the answer with more detailed example. It now deals with data more generically, like it doesn't assume what are the entries of 'contents' and such, but it knows that each type like 'people' or 'pets' are an array.
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
pets: [
{
name: "Sweety",
age: 3,
},
{
name: "Kitty",
age: 5,
},
],
},
};
var App = React.createClass({
render: function () {
// Get the keys in data.content. This will return ['people', 'pets']
var contentKeys = Object.keys(data.content);
// Now start iterating through these keys and use those keys to
// retrieve the underlying arrays and then extract the name field
var allNames = contentKeys.map((t) =>
data.content[t].map((e) => <div>{e.name}</div>)
);
return <div>{allNames}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the latest JSBin: https://jsbin.com/coyalec/4/edit?html,js,output

ImmutableJS: Convert List to indexed Map

This question is about Immutable.js library.
I have a List<T>, where T is {name: string, id: number}. I want to convert it to Map<number, T>, with id of T to the keys. Using standard method toMap gives me a Map with sequential indexes, and there is no way to hook there. And no method like indexBy or other. how to do that?
You can do it with a reducer like this:
function indexBy(iterable, searchKey) {
return iterable.reduce(
(lookup, item) => lookup.set(item.get(searchKey), item),
Immutable.Map()
);
}
var things = Immutable.fromJS([
{id: 'id-1', lol: 'abc'},
{id: 'id-2', lol: 'def'},
{id: 'id-3', lol: 'jkl'}
]);
var thingsLookup = indexBy(things, 'id');
thingsLookup.toJS() === {
"id-1": { "id": "id-1", "lol": "abc" },
"id-2": { "id": "id-2", "lol": "def" },
"id-3": { "id": "id-3", "lol": "jkl" }
};

How to change name of JSON key?

children: [
{
name:'Basic Ext Layouts',
expanded: false,
children:[
{
name:'Absolute',
id:'absolute',
leaf:true,
},{
...
}]
}]
Is it possible to change children to mydata?
Is it possible to change children to mydata?
Yes. Setup treestore's proxy to use reader with root config set to 'mydata':
var store = Ext.create('Ext.data.TreeStore', {
model: 'MyModel',
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'mydata' // << this is required
}
},
root: {
myData: [
{
name:'Basic Ext Layouts',
Here is working example.
JSON format is merely a String in javascript's point of view. So you could manipulate the JSON string with associated method.
JSON.
// The original
obj = {
children: [
{
name:'Basic Ext Layouts',
expanded: false,
children:[
{
name:'Absolute',
id:'absolute',
leaf:true,
}]
}]
}
// Transfer the object to a JSON string
var jsonstr = JSON.stringify(obj);
// HERE you do the transform
var new_jsonstr = jsonstr.replace('"children"', '"mydata"');
// You probably want to parse the altered string later
var new_obj = JSON.parse(new_jsonstr);