ImmutableJs : Updating a List in nested Map - javascript

I have a hard reading the ImmutableJS and other questions answers... It seems simple, I have a Map like this :
{
foo: [
{id: 1, name: 'John'},
{id: 2, name: 'Christine'},
{id: 3, name: 'Frank'},
{id: 4, name: 'Jenny'},
]
}
How can i update change "John" to "Johnny" ?

From the docs you can use this:
newMap = oldMap.setIn(['foo', 0, 'name'], 'Johnny');
You pass an array of keys, then the value.

Related

Iterate array objects in js

I have an array objects
it looks like
\[
{id: 1, name: 'first', properties: \[{id: 1, name: 'propName1'}, {id: 2, name: 'propName2'}\]},
{id: 2, name: 'second', properties: \[{id: 1, name: 'propName1'}, {id: 2, name: 'propName2'}\]},
{id: 3, name: 'third', properties: \[{id: 1, name: 'propName1'}, {id: 2, name: 'propName2'}\]},
\]
I want to display first name of object for example 'first' and then I want to display names of properties objects propName1, propName2
so I want to see
first
propName1
propName2
second
propName1
propName2
third
propName1
propName2
Could you help me, guys?
I tried
{filters.map((filter) => {
let propss = ArrayFrom(filter.properties);
propss.map((prop) => (
<div>{prop.displayName}</div>
))
return(
<div className={style.title}>{filter.displayName}</div>
)
filter.properties.map((prop) => {
return (
<>
<div className={style.title}>{filter.displayName}</div>
<div>{prop.displayName}</div>
</>
);
});
})}
and I tried to save array via reduce, but without any result
First of all, you should not name yout array 'filter' since this can be confused with the Array.prototype.filter method ;)
Then you have an array of objects containing arrays, so you should iterate at the two level (in case your real structure actually gots more depth, you probably need to take a recursive approach).
considering your entry point :
const data = [
{
id: 1,
name: 'first',
properties: [
{id: 1, name: 'propName1'},
{id: 2, name: 'propName2'}
]
}, {
id: 2,
name: 'second',
properties: [
{id: 1, name: 'propName1'},
{id: 2, name: 'propName2'}
]
}, {
id: 3,
name: 'third',
properties: [
{id: 1, name: 'propName1'},
{id: 2, name: 'propName2'}
]
},
]
the two iterations couls look like somthing like that :
return data.map(entry => (
<>
<div className={style.title}>{entry.name}</div>
{entry.properties.map(prop => (
<div>{prop.name}</div>
))}
<>
))

How to check if a sub-array contains all elements of another array javascript

I have an array of projects called rawProjects which looks like this:
rawProjects = [
{
id: 1,
name: "proj1",
technology: [
0: {id: 21, project_id: 1,name: "java"},
1: {id: 22, project_id: 1,name: "c++"}
]
},
{
id: 2,
name: "proj2",
technology: [
0: {id: 23, project_id: 2,name: "sql"},
1: {id: 24, project_id: 2,name: "python"},
2: {id: 25, project_id: 2,name: "react"}
]
}
]
I also have an array of technology called tempTags which contains the technologies that the user enters to search from. So far I have been able to do the OR case where in I return the projects which contain either of the technologies mentioned by the user using:
const filteredProjects = rawProjects.filter(x => x.technology.some(g => tempArr.includes(g.name)))
So for example if tempTags = [sql, c++] both projects will be returned.
How do I implement the AND case such that only projects that contain both of these technologies are returned. Eg if tempTags = [java, c++] , only the first project will be returned. If tempTags = [sql, c++], nothing will be returned?
Iterate over the tempTags and check that .every one of them is included:
const rawProjects = [
{
id: 1,
name: "proj1",
technology: [
{id: 21, project_id: 1,name: "java"},
{id: 22, project_id: 1,name: "c++"}
]
},
{
id: 2,
name: "proj2",
technology: [
{id: 23, project_id: 2,name: "sql"},
{id: 24, project_id: 2,name: "python"},
{id: 25, project_id: 2,name: "react"}
]
}
]
const tempTags = ['java', 'c++'];
const filtered = rawProjects.filter(
p => {
const techNames = p.technology.map(({ name }) => name);
return tempTags.every(
tag => techNames.includes(tag)
);
}
);
console.log(filtered);
You'll also need to fix your syntax: arrays do not have key-value pairs, only values. (Remove the 0:, 1:, etc), and make sure to put commas in between array values (there should be a comma after "python"})

JSON-server. Filter by nested value

I have DB (use json-server) like this:
DB = {
products: [
{id: 0, name: 'aaa', price: 10},
{id: 1, name: 'bbb', price: 20},
{id: 2, name: 'ccc', price: 50},
{id: 3, name: 'ddd', price: 1}
]
};
And array of ids:
cartItemsIds: [0, 3];
How can I get array of objects from DB with ids from cartItemsIds ?
Solved. If anyone needs:
`products?id=${cartItemsIds.join('&id=')}`
You can loop over your products from db like so:
for(const product of DB.products) {
if(cartItemsIds.includes(product.id)) {
console.log(product);
}
}

Recursive function to find top level parent given an id

Given the following data set:
const accounts = [
{id: 2, children: [1,22,69], parentId: null},
{id: 3, children: [140, 122, 580], parentId: null},
{id: 1, children: [4,5,6], parentId: 2},
{id: 22, children: [8,9,2], parentId: 2},
{id: 4, children: [45,54,61], parentId: 1},
{id: 6, children: [40,89,20], parentId: 1},
{id: 40, children: [], parentId: 6},
....
]
I need to create a function that takes and id as argument and returns a tree, starting with the top most level parent and it's children (and siblings).
In the above example, there are only 2 top level "accounts", id:2 and id:3. So the function call might look like findTree(89) , it should return the tree starting with the account id 2, and it's children, but will obviously leave out account id 3 and it's children, since that top level account has nothing to do with top level account of id 2, so the ideal response would be:
{
id: 2,
children: [
{ id: 1, children: [{id: 540, children: [{ id: 78},{}], parentId:1], parentId: 2},
.....
],
parentId: null
}
What would be the best way to go about it ? I've tried a recursive function but I'm not getting anywhere near to a solution.
EDIT: Here part of the code:
(groupArray is an array containing all items in a flat list, without hierarchy)
const makeTreeById = itemId => {
const startNode = _.find(groupArray, {id: itemId}) // grab the actual item, not the id
findTopParent(startNode)
}
and then the findTopParent fn
const findTop = item => {
let top = item;
if(top.parentId) {
top = _.find(groupArray, {id: top.parentId}
return findTop(top)
}
return top;
}
I was creating that function to simply have it return the top level account and from there I was planning on constructing the actual tree, the problem is that top does get me the top level but at some point it get reassigned with the immediate parent.
SECOND EDIT: Sorry about all the confusion guys, as you can see, I'm really new.
I have an array that includes all items I would need. So it kinda looks like this:
// children here are only ids, not the actual elements, the element are part of // the list, but the children array for each element is just a reference.
data = [
{id: 1, children: [4,5,6], parentId: null},
{id: 2, children: [7,8,9], parentId: null},
{id: 3, children: [10,11,12], parentId: null},
{id: 4, children: [13,14,15], parentId: 1},
{id: 10, children: [20,21,22], parentId: 3}
{id: 14, children: [], parentId: 4}
....
]
You can find the desired results with function topParent. Just look for parent being null in each iteration.
const accounts = [
{id: 2, children: [1,22,69], parentId: null},
{id: 3, children: [140, 122, 580], parentId: null},
{id: 1, children: [4,5,6], parentId: 2},
{id: 22, children: [8,9,2], parentId: 2},
{id: 4, children: [45,54,61], parentId: 1},
{id: 6, children: [40,89,20], parentId: 1},
{id: 40, children: [], parentId: 6}
];
function topParent(id) {
var obj = accounts.find((v) => v.id == id);
return obj.parentId == null ? obj : topParent(obj.parentId)
}
console.log(topParent(6));
actually they are many way to achieve the expected tree. In performance manner you should determine if you will have complexity (in term of iteration) on the deep of your tree or | and on how many items in total you will have.
I have assume the complexity will be more on how many items in total you will have.
exemple : big amount of accounts with only small amount of nested childrens.
Introduction : Following you have type and sample array.
interface IEntity {
id: number;
children: number[];
parentId?: number;
}
interface IEntityNested {
id: number;
children: IEntityNested[];
parentId?: number;
}
const accounts: IEntity[] = [
{id: 1, children: [3], parentId: null},
{id: 2, children: [], parentId: null},
{id: 3, children: [4], parentId: 1},
{id: 4, children: [], parentId: 3},
];
For that i prupose you to start by searching for any particular id what is the top of you tree. The element which doesn't have any other top element.
const findTopParent = (id: number): IEntity => {
let account = accounts.find(acc => acc.id === id);
if(account.parentId !== null) {
account = findTopParent(account.parentId);
}
return account;
};
For id 4 it should return account id 1
const topParent = findTopParent(4);
console.log(topParent.id); // Print 1.
then from your topParent you can build the nested tree from the top to the bottom.
const buildTreeFromSpecificAccount = (account: IEntity): IEntityNested => {
const nestedAccount = {...account,children: []};
account.children.forEach(childId => {
nestedAccount.children.push(
buildTreeFromSpecificAccount(
accounts.find(acc => acc.id === childId)
)
);
})
return nestedAccount;
}
// Build the tree from the top parent.
const tree = buildTreeFromSpecificAccount(topParent);
And voilĂ  !
Side note :
You can way more improve the performance by changing your data array by indexed object like following :
const accountOrdered: {[id: number]: IEntity} = {
1: {id: 1, children: [3], parentId: null},
2: {id: 2, children: [], parentId: null},
3: {id: 3, children: [4], parentId: 1},
4: {id: 4, children: [], parentId: 3},
};
Like this instead of doing accounts.find(acc => acc.id === childId) looping on your array to find entry by id. you can do accountOrdered[childId]
live sample

Ramdajs keyBy equivalent of lodash

I have an array that I want to transform into an object. For example:
const arr = [{id: 1, key: ''}, {id: 2, key: ''}];
I want the result to be:
const object = { 1: {id: 1, key: ''}, 2: { id: 2, key: ''}}
With lodash I can use the keyBy function, but I am working with ramda and did not find this functionality there.
In case anyone still finds this via search, the correct answer is indexBy, added in mid-2016.
const list = [
{ id: "xyz", title: "A" },
{ id: "abc", title: "B" },
];
R.indexBy(R.prop("id"), list);
//=> {abc: {id: 'abc', title: 'B'}, xyz: {id: 'xyz', title: 'A'}}
See Also:
Github: Ramda Wiki "What Ramda Function Should I Use?"
Github: Ramda Issue #931 - "sister to groupBy"
You can solve this with very basic reduce function.
function keyBy(entities, id = "id") {
return entities.reduce((acc, entity) => {
acc[entity[id]] = entity;
return acc;
}, {});
}

Categories