Generate Children element based on number of keys in object [duplicate] - javascript

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 3 years ago.
I have my object that is stored in variable val.Main.widgets. I also have variable that functions as a data tree. What I need is to generate as many children elements as there are keys in my object that is stored in val.Main.widgets. If I console log this: console.log(Object.keys(val.Main.widgets).length;, it returns 8 so in this case I need to generate 8 children elements.
I am guessing I need some sort of cycle, but I really dont know where to start, hence why I am asking here.
Here is my object:
And here is my tree variable:
const tileTree = [
{
name: val.Main.name,
children: [
{
name: val.Main.widgets['E1EV7'].name,
},
{
name: val.Main.widgets['E70ZT'].name,
},
],
},
];
Thank you for any advice.

You do not need lodash for this. You want to use Array.map on the result of Object.keys.
const content = val.Main.widgets;
const keys = Object.keys(content);
const children = keys.map(key => content[key]);
Then in your tileTree you simply set children to children.
const tileTree = [
{
name: val.Main.name,
children,
},
];
This will give you all the properties of the val.Main.widgets object. If you only want specific ones, you can destructure them in your map function.
...
// Suppose we only want 'name'.
const children = keys.map(key => {
const { name } = content[key];
return { name };
});
...

You can use
Object.keys(val.Main.widgets).map(widgetKey => {
const widget = val.Main.widgets[widgetKey]
return (
<div key={widgetKey}>
<h1>This is widget : {widget.name}</h1>
</div>
)
}

const tileTree = [
{
name: 'test',
children: [
{
name: 'test1'
},
{
name: 'test2'
},
{
name: 'test3'
},
{
name: 'test4'
},
{
name: 'test5'
},
{
name: 'test6'
}
],
},
];
const createLi = (arr) => {
for (let i = 0; i < arr[0].children.length; i += 1) {
let li = document.createElement("li");
let ol = document.getElementById('list');
li.innerHTML = arr[0].children[i].name;
ol.appendChild(li);
}
}
createLi(tileTree);
https://jsfiddle.net/os20wdLh/

Object.keys is a function that returns an array. The array has a foreach method
var lunch = {
sandwich: 'ham',
snack: 'chips',
drink: 'soda',
desert: 'cookie',
guests: 3,
alcohol: false,
};
Object.keys(lunch).forEach(function (item) {
console.log(item); // key
console.log(lunch[item]); // value
});
Other way is by using lodash module from npm or yarn. example where _ is the lodash module:
_.times(8, i => {
schedule.push({
date: moment()
.add(i, "days")
.format("YYYY-MM-DD"),
times: [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
});
});
You can replace the 8 with your .length code.

Related

How to add elements in an object while traversing through an array using map?

I am having an array like this :
arr = [ {id:0,name:Mark} , {id:1,name:Ron}, {id:2,name:Henry}, {id:3,name:Rose}].
I want to create an object like this :
obj1 = { Mark:false, Ron:false, Henry:false, Rose:flase }
I am using map to traverse through the array like this
let obj1 = {};
obj1 = arr.map((item)=> {
obj1[item.name] = false;
})
How can I achieve the following result?
You could map entries and build an object from the pairs.
const
data = [{ id: 0, name: 'Mark' }, { id: 1, name: 'Ron' }, { id: 2, name: 'Henry' }, { id: 3, name: 'Rose' }],
result = Object.fromEntries(data.map(({ name }) => [name, false]));
console.log(result);
Object.fromEntries() is probably the best idea. But you could also use reduce, if you got more operations on the array and want to stick to the "pipe" approach.
const arr = [
{ id: 0, name: 'Mark' },
{ id: 1, name: 'Ron' },
{ id: 2, name: 'Henry' },
{ id: 3, name: 'Rose' }
];
const objA = arr
.reduce((previous, { name }) => ({ ...previous, [name]: false }), {});
const objB = arr
.reduce((previous, { name }) => {
previous[name] = false;
return previous;
}, {});
The spreach operation {...obj} for objA does effectivly copy the object on each extension, which might not be desirable. But the modern JavaScript engines simplify those expressions anyways.
objB is the more standard approach for me. One additional benefit, in regards to Object.fromEntries() is that you can have some form of standard or default object / settings, which you can use as the start of the reduce (the second parameter) and evaluate in the collection function.
All three options are valid and depend on your code style.

How to compare two different arrays which has different property names and remove unmatched ones in javascript?

I havve two different arrays with different property names like below
arrayA = [
{ id: 20, name: 'Jason' },
{ id: 15, name: 'Harry' },
{ id: 5, name: 'Clara' },
{ id: 9, name: 'Melonie' }
]
arrayB = [
{ courseID: 12, studentID: 20 },
{ courseID: 12, studentID: 15 }
]
I want to compare these two different arrays and remove unmatched ids from arrayA. For comparison, id field of arrayA and studentID field of arrayB matters. if these fileds aren't equal to each other, they should be removed from arrayA.
Expected is below
arrayA = [{id: 20, name: 'Jason' }, { id: 15, name: 'Harry' }]
Here is what I tried below but didn't work. Gave me empty array.
filteredElements = this.arrayA.map(e => e.id).filter(
val => this.arrayB.indexOf(val.studentID) !== -1
);
You can do that in following steps:
Use map() on arrayB and create array of courseID.
Then create a Set() from that Array
Then use filter() arrayA and check whether id of object exists in above created Set or not using Set.prototype.has()
const arrayA = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const arrayB =[{courseID:12,studentID:20},{courseID:12,studentID:15}];
const ids = new Set(arrayB.map(x => x.studentID));
const res = arrayA.filter(x => ids.has(x.id));
console.log(res);
let arrayA = [{id: 20,name: 'Jason'},{id: 15,name: 'Harry'},{id: 5,name: 'Clara'},{id: 9,name: 'Melonie'}]
let arrayB = [{courseID: 12,studentID: 20},{courseID: 12,studentID: 15}];
let filtered=arrayA.filter(obj =>{ if(arrayB.find(course => course.studentID == obj.id))return true;return false;
});
console.log(filtered);
Try this:
var studentIds = arrayB.map(course => course.studentID);
var result = arrayA.filter(student => studentIds.includes(student.id));
The variable result contains your result.
Create a dictionary from courseMembers, keyed on studentID, to enable O(1) lookup.
Filter students according to the dictionary.
const students = [{id:20,name:'Jason'},{id:15,name:'Harry'},{id:5,name:'Clara'},{id:9,name:'Melonie'}]
const courseMembers = [{courseID:12,studentID:20},{courseID:12,studentID:15}]
function withCourses(students, courseMembers) {
const map = courseMembers.reduce((acc, {studentID}) =>
(acc[studentID] = true, acc), {})
return students.filter(({id}) => map[id])
}
const result = withCourses(students, courseMembers)
console.log(result) // [{ id:20, name:"Jason" },{ id:15, name:"Harry" }]

How to access object property by variable in Javascript [duplicate]

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 3 years ago.
I have an object like
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
I want to access its property dynamically. I want to access id property's value from pivot from first object of this array. And it's should be dynamic.
This is what I tried already.
let s = "0.pivot.id"
let res = arr[s]
console.log(res)
I can access by arr[0].pivot.id but this is not my case. I want it dynamically.
You can split the string and loop through it updating a variable refrencing the last found value :
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
let s = "0.pivot.id";
const getValue = (arr, str) => {
let ref = arr;
const keys = str.split(".");
keys.forEach(k => {
ref = ref[k];
});
return ref;
};
const result = getValue(arr, s);
console.log(result);
what you tried would give you a property which key was 0.pivot.id. So it might work if your object looks like this
{
'0.pivot.id': 'something'
}
There is no native way to access deeper level of an object dynamically. You would need to use recursion for that.
It's quite easy though, You could simply split your key into an array of keys and then recursively check your array for matching keys.
let arr = [
{
title: "hello",
pivot: {
id: 1,
bid: 3
}
},
{
title: "home",
pivot: {
id: 2,
bid: 3
}
},
{
title: "nice",
pivot: {
id: 3,
bid: 3
}
}
];
function getDynamicKeyRecursively(object, key) {
// the key needs to be an array,
// if it isn't, we split it into an array
if(typeof key === 'string') {
key = key.split('.');
}
// we get the current value of the current object
let currentValue = object[key[0]];
// remove the first index of the key
key.shift()
// if the current value is an object or an array, we recursively check this value for what we want
// otherwise, we return the value.
return Array.isArray(currentValue) || typeof currentValue === 'object' ? getDynamicKeyRecursively(currentValue, key) : currentValue;
}
console.log(getDynamicKeyRecursively(arr, '1.pivot.id'));

How to create function to create array of keys? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
Suppose I have an array of users:
const users =[
{
id:1,
name:'bob',
},
{
id:2,
name:'sally',
},
{
id:3,
name:'bob',
age:30,
}
];
Now I want to extract the keys by either name,id or age(example for name):
const arrangeByName = arrangeBy('name');
arrangeByName(users);
So the result would be:
['bob','sally'];
My arrangeBy function looks like this:
const go = A => key => {
return A.map(a => a.key);
};
export default go;
But when I run this I get:
A.map is not a function
How can I write a function that can extract keys in an array? Also note that any duplicates are not created in the output.
Since you want to exclude objects for which the given key property is not present, and want to exclude duplicates, things become a little more complex.
This solution filters out the objects for which the property is not present, and uses a Set to avoid duplicates:
const arrangeBy = key => A => [...A.reduce((s, v) => key in v ? s.add(v[key]) : s, new Set())];
Complete snippet:
const users = [{
id: 1,
name: 'bob',
}, {
id: 2,
name: 'sally',
}, {
id: 3,
name: 'bob',
age: 30,
}];
const arrangeBy = key => A => [...A.reduce((s, v) => key in v ? s.add(v[key]) : s, new Set())];
const arrangeByName = arrangeBy('name');
const arrangeByAge = arrangeBy('age');
console.log(arrangeByName(users));
console.log(arrangeByAge(users));
I see two issues. One, your arguments are in the wrong order as it seems you want arrangeBy to accept a key and return a function that accepts users. Second, a.key will try to access a property called "key" on the object, which I doubt is what you are trying to do - you will instead want to do a[key]
// get values of key, removing duplicates
const arrangeBy = key => arr =>
[...arr.reduce((set, el) => set.add(el[key]), new Set)]
const arrangeByName = arrangeBy('name')
const arrangeById = arrangeBy('id')
const users = [{id: 1, name: 'bob'}, {id: 2, name: 'sally'}, {id: 3, name: 'bob'}]
console.log(arrangeByName(users))
console.log(arrangeById(users))
You can create Array.prototype.arrangeBy:
Array.prototype.arrangeBy = function(key) {
const array = this
.filter(el => !!el[key])
.map(el => el[key])
return [...new Set(array)]
}
const users = [{
id: 1,
name: 'bob'
}, {
id: 2,
name: 'sally'
},
{
id: 3,
name: 'bob',
age: 30
}
]
console.log(users.arrangeBy('id'))
console.log(users.arrangeBy('name'))
console.log(users.arrangeBy('age'))
function arangeByKey(key) {
return function (arr) {
return arr.map(item => item[key]);
};
}
const arangeByName = arangeByKey('name');
const arrangeById = arangeByKey('id');
console.log(arangeByName(users));
console.log(arrangeById(users));
// If array contains unique element
console.log([... new Set(arangeByName(users))]);

Compare 2 arrays and assign matching value [duplicate]

This question already has answers here:
Merge property from an array of objects into another based on property value lodash
(5 answers)
Closed 4 years ago.
I have 2 array of objects
The first one called data:
const data = [
{
id: 1,
nombre: 'Piero',
},
{
id: 4,
nombre: 'Nelson',
},
{
id: 7,
nombre: 'Diego'
},
]
and the second called subs:
const subs = [
{
id: 1,
name: 'Temprano',
},
{
id: 4,
name: 'A tiempo',
},
{
id: 7,
name: 'Tarde'
},
]
In which I want to compare that if they have the same ID, the subs array will pass its name value to it and if it does not match that it puts a '-' in the data array, try this way:
data.forEach((d)=>{
subs.forEach((s)=>{
if(d.id === s.id){
d.subname = s.name;
}
else {
d.subname = '-';
}
});
});
But always assign the values with '-' as if it does not match any. What part am I doing wrong? Is there any other simpler way to do this? I would greatly appreciate your help.
The size of the subs array may vary.
It looks like you are not exiting the inner loop when a successful match is found.
In the first example where you are looking for a match for Piero, in your first iteration 1===1 and d.subname is correctly set to 'Temprano'. However, you then continue to compare the values- 1 !== 4 so Temprano is overwritten with '-', and 1 !== 7 so it is overwritten again.
An alternate approach:
data.forEach(d => {
const match = subs.find(s => s.id === d.id);
d.subname = match ? match.name : '-';});
I'd also recommend adding a case where you're not expecting to find a match, so you can see that it works in both cases!
https://codepen.io/anon/pen/MGGBLP?editors=0010
const data = [
{
id: 1,
nombre: 'Piero',
},
{
id: 4,
nombre: 'Nelson',
},
{
id: 7,
nombre: 'Diego'
},
];
const subs = [
{
id: 1,
name: 'Temprano',
},
{
id: 4,
name: 'A tiempo',
},
{
id: 7,
name: 'Tarde'
},
];
// by caching one of the arrays in an object, it reduces the run time to linear.
const obj = subs.reduce((acc, item) => {
acc[item.id] = item;
return acc;
})
data.forEach(d => {
if (d.id in obj) {
d.subname = obj[d.id].name;
} else {
d.subname = '-';
}
});
console.log(data);
You just need two lines for this:
var findIds = id => subs.find(findId => findId.id === id);
data.forEach(findId => Object.assign(findId, findIds(findId.id)));
Your data array object should now include the name property from it's respective id sharing object in subs array.
jsFiddle: https://jsfiddle.net/AndrewL64/9k1d3oj2/1/

Categories

Resources