Related
what would be the result of my code ? I am expecting to have as result one single array of length 1 , I want to output only values of d variable that haven't been updated in my var2 variable but I get an array of length 2 , I want to have output
{name : "david", age : 23, day : 23}
const d = [{name : '',age : '',day :23}]
const var2 = [...d, { name : 'david', age : 22}]
console.log(var2)
You are not using the spread operator correctly. You should use it to merge all elements of d[0] with an object containing your updated values.
const d = [{name : '',age : '',day :23}]
// for d containing only one element
const var2 = [{...d[0], name : 'david', age : 22}]
// will result in [{name: '', age: '', day: 23, name: 'david', age: 22}] and be merged by keeping the right-most value
// for all elements in d
const var3 = d.map(el => {
return {...el, name : 'david', age : 22}
})
console.log(var2)
console.log(var3)
Think of it this way:
d is an array of objects
{ name : 'david', age : 22} is an object literal
When you use the spread operator on d, you are telling it to take each object in d and place it into var2, then at the end, append the { name : 'david', age : 22}.
So the result would be an array with all the items you had in d + the object literal { name : 'david', age : 22}.
To get your expected result {name : "david", age : 23, day : 23} merge two objects like shown below.
merge Object like {...object1, ...object2}
const d = [{name : '',age : '',day :23}]
const var2 = {...d[0], ...{ name : 'david', age : 22}}
console.log(var2)
Spread operator you use in line 2 is used when all elements from an object or array need to be included in a list of some kind.
Basically what happens in your code ->
Array d has 1 item, so when you try to define var2 it takes all elements from array d ( 1 in our case ) and add { name : 'david', age : 22} to it.
In result you get array of two items.
For example:
const array1 = [1, 2, 3]
const array2 = [...array1,4, 5]
// array2 now is [1, 2, 3, 4, 5]
console.log(array2)
the (...) is Array/Object spread operator js spread operator
What the code above does, is to spread over the d object and get all its properties, then overwrite the existing properties with the ones we’re passing. It copies the properties of the d object, over to the newly created object. So you are getting this output. Try the below code:
<script>
const d = [{name : '',age : '',day :23}]
const var2 = [{...d[0], name : 'david', age : 22}]
console.log(var2)
</script>
You can also achieve the same using below code
<script>
const d = {name : '',age : '',day :23}
const var2 = {...d, name : 'david', age : 22}
console.log(var2)
</script>
It will override the name and age
This question already has answers here:
Merge 2 arrays of objects
(46 answers)
Closed 1 year ago.
Say I have two data arrays for a ticketed event. One is attendees:
[
{name: 'Jack', ticket_code: 'iGh4rT'},
{name: 'Lisa', ticket_code: 'it1ErB'}
]
The other is tickets:
[
{code: 'iGh4rT', name: 'General Admission'},
{code: 'it1ErB', name: 'VIP'}
]
Now say I want to display a table like this:
Name
Ticket Name
Jack
General Admission
Lisa
VIP
I am struggling with doing this efficiently. I can display a table with one array no problem like something like this:
for (let i = 0; i < attendees.length; i++){
const row = `<tr>
<td>${attendees[i].name}</td>
<td>${attendees[i].ticket_code}</td>
</tr>`
document.getElementById('TableBody').innerHTML += row
I need to somehow 'query' the tickets array with the code from the attendees array for that particular person, get the name of the ticket, and supplant the ticket name instead of the code.
With SQL something like this is easy, but is one able to "query" an array and get a specific property? Should I construct a whole new array with the needed info? What is the best way to do this that would work for large unordered datasets?
You could take one of your array as an object with code as key for the object and map the other array with wanted data and the previous stored data from the object.
const
attendees = [{ name: 'Jack', ticket_code: 'iGh4rT' }, { name: 'Lisa', ticket_code: 'it1ErB' }],
tickets = [{ code: 'iGh4rT', name: 'General Admission' }, { code: 'it1ErB', name: 'VIP' }],
ticketsByCode = Object.fromEntries(tickets.map(o => [o.code, o])),
table = attendees.map(({ name, ticket_code }) => [name, ticketsByCode [ticket_code].name]);
console.log(table);
try this:
let a = [
{name: 'Jack', ticket_code: 'iGh4rT'},
{name: 'Lisa', ticket_code: 'it1ErB'}
];
let b = [
{code: 'iGh4rT', name: 'General Admission'},
{code: 'it1ErB', name: 'VIP'}
];
let c = b.map(item => {
return {
tiketName: item.name,
...a.find(itemA => itemA.ticket_code == item.code)
}
});
console.log(c);
I have an array of objects, that contains properties that are objects:
let allPersons = [
{ id: "abcdefg",
name: "tom",
...
phone: {
brand: "blah"
id: "hijklm"
...
}
},
{ id: ....}, {...}, {...}
];
What I need to do is filter those objects and returning all the phones, filtering them by id so all phones returned are unique.
I tried to retrieve first all the phones:
// allPersons is the full array mentioned above
let phones = [...new Set(allPersons.map(person => person.phone))];
then I tried to return all the unique phones, but unsuccessfully:
let result = phones.map(phone => phone.id).filter((value, index, self) => self.indexOf(value) === index)
This returns only the unique ids of the phones, but I want the entire object. What can I do?
UPDATE:
phone Ids are NOT unique, e.g. nokia3310 has id 1, nokia3330 has id 2, etc: so tom and john can have the same phone and phone ids could be duplicated!
Make an object indexed by IDs instead, then take the object's values:
const phonesById = Object.fromEntries(
allPersons.map(
({ phone }) => [phone.id, phone]
)
);
const uniquePhones = Object.values(phonesById);
If you're trying to get the phone object in each object of the array, then the code below will do that for you.
It gets the phone object and stores it in a
var objArr = [
{id: "abcdefg", name: "tom", phone: {brand: "blah", id: "hijklm"}},
{id: "guidiuqwbd", name: "john", phone: {brand: "hihihih", id: "ayfva"}},
{id: "yuygeve", name: "doe", phone: {brand: "hahahah", id: "cqcqw"}}
]
var allPhoneObjects = [];
objArr.forEach(function(currObj){
var phoneObj = currObj.phone;
allPhoneObjects.push(phoneObj);
});
console.log(allPhoneObjects);
I propose you the following solution
let uniques = new Set();
const phones = allPersons.filter(({phone}) => (
uniques.has(phone.id) ? false : !!uniques.add(phone.id)
)).map(p => p.phone)
Basically, we define a Set to record ids of the phones already processed, and a filter function on the allPersons array, that returns only the phones not already in the Set. We complete with the map to extract only the portion of JSON needed
EDIT
You can use just one function on the allPersons array using the reduce function
let uniques = new Set();
const phones = allPersons.reduce( (filtered, {phone}) => {
if (!uniques.has(phone.id)) {
filtered.push(phone);
uniques.add(phone.id);
}
return filtered
}, [])
I am using ReactJS. I have an object which looks like this:
{
autumn=firstContactPersonName: "John",
autumn=firstContactPersonPhone: "46442644",
autumn=secondContactPersonName: "Jhonny",
autumn=secondContactPersonPhone: "46442644",
christmas=firstContactPersonName: "Tommy",
christmas=firstContactPersonPhone: "46442644",
christmas=secondContactPersonPhone: "Thomas",
winter=firstContactPersonPhone: "46442644",
winter=firstContactPersonName: "Peter",
winter=secondContactPersonName: "Tom",
winter=secondContactPersonPhone: "44664455"
}
How can I group them based on autumn, christmas, winter. So one object with autumn have the autumn fields, the second one christmas have the christmas field, and the third one winter have the winter fields?
And so on. All fields will have a segment name before =, so I can easily see what kind of segment they belong to.
This is achievable with pure JS, no need for lodash (which I'm not familiar with).
This function takes every property of your input object, splits the key around the equals sign for the season part (prefix) and rest (appendix). Afterwards it looks for an object in the output array with the same season and adds the properties to it. If there is no object with specified season, it creates a new one.
function processData(inputObj) {
var data = [];
for (var key in inputObj) {
var prefix = key.split("=")[0];
var appendix = key.split("=")[1];
var dataObject = data.find(o => o.season == prefix);
if (!dataObject) {
dataObject = {season: prefix};
data.push(dataObject);
}
dataObject[appendix] = inputObj[key];
}
return { data };
}
produces this output:
{
"data": [
{
"season": "autumn",
"firstContactPersonName": "John",
"firstContactPersonPhone": "46442644",
"secondContactPersonName": "Jhonny",
"secondContactPersonPhone": "46442644"
},
{
"season": "christmas",
"firstContactPersonName": "Tommy",
"firstContactPersonPhone": "46442644",
"secondContactPersonPhone": "Thomas"
},
{
"season": "winter",
"firstContactPersonPhone": "46442644",
"firstContactPersonName": "Peter",
"secondContactPersonName": "Tom",
"secondContactPersonPhone": "44664455"
}
]
}
You can produce your groups by looping over the keys in the object. Split the key on = and capture the results. The first element should be the group, the second the property to access within this group.
Create a new object if a group doesn't yet exist. Then set the property within the group equal to the value of the original object.
const input = {
"autumn=firstContactPersonName": "John",
"autumn=firstContactPersonPhone": "46442644",
"autumn=secondContactPersonName": "Jhonny",
"autumn=secondContactPersonPhone": "46442644",
"christmas=firstContactPersonName": "Tommy",
"christmas=firstContactPersonPhone": "46442644",
"christmas=secondContactPersonPhone": "Thomas",
"winter=firstContactPersonPhone": "46442644",
"winter=firstContactPersonName": "Peter",
"winter=secondContactPersonName": "Tom",
"winter=secondContactPersonPhone": "44664455"
};
const output = {};
for (const key in input) {
const [season, property] = key.split("=", 2);
if (!output[season]) output[season] = {};
output[season][property] = input[key];
}
console.log(output);
I find my explanation a bit confusion, but I hope that combined with the code snippet you understand what I'm saying.
Use Object.entries() to generate an array of [key, value] pairs, and iterate with Array.reduce(). For each pair, split the key by = to get the group key, and the value key, create the group's object if none exists, and assign the value to the object.
const data = {"autumn=firstContactPersonName":"John","autumn=firstContactPersonPhone":"46442644","autumn=secondContactPersonName":"Jhonny","autumn=secondContactPersonPhone":"46442644","christmas=firstContactPersonName":"Tommy","christmas=firstContactPersonPhone":"46442644","christmas=secondContactPersonPhone":"Thomas","winter=firstContactPersonPhone":"46442644","winter=firstContactPersonName":"Peter","winter=secondContactPersonName":"Tom","winter=secondContactPersonPhone":"44664455"}
const result = Object.entries(data)
.reduce((r, [k, v]) => {
const [gKey, key] = k.split('=') // get the key
r[gKey] = r[gKey] || {} // generate the object if it doesn't exist
r[gKey][key] = v // assign the value to the object
return r
}, {})
console.log(result);
I'm parsing a JSON message which looks something like:
{
staff : [
{name : 'John', department : 'Math'},
{name : 'Sally', department : 'Science'},
],
students : [
{name : 'Bob', department : 'Law'},
{name : 'Lisa', department : 'IT'}
]
}
From which I'd like to pull out an array of each separate value.
i.e.
names -> ['John', 'Sally', 'Bob', 'Lisa']
At the moment I'm doing something like
var names = [];
msg.staff.forEach(function(e) { names.push(e.name) })
msg.students.forEach(function(e) { names.push(e.name)})
This feels overly verbose, just wondering if there's a cleaner way to approach this (for every attribute). I'm already including lodash in this project.
You can use _.pluck to get the value of a property of each object in an array:
_.pluck(obj.staff.concat(obj.students), 'name')
Your instinct is right; you don't need a mutable array to do this with lodash.
_(obj).map().flatten().pluck('name').value();
This version works for any number of array values in o.
JSBin
Edit missed that you had lodash available, will leave this vanilla JS version here anyway.
You could use map to be more concise:
var directory = {
staff : [
{name : 'John', department : 'Math'},
{name : 'Sally', department : 'Science'},
],
students : [
{name : 'Bob', department : 'Law'},
{name : 'Lisa', department : 'IT'}
]
};
var names = directory.staff.concat(directory.students).map(function(person) {
return person.name;
});
If you don't know the individual key names before hand, you could do:
Object.keys(directory).map(function(key) {
return directory[key]
}).reduce(function(p,c){
return p.concat(c)
}).map(function(person) {
return person.name;
});
I didn't catch the requirement of getting an array of all values stored under each key, this should do it though:
Object.keys(directory).map(function(key) {
return directory[key];
}).reduce(function(p,c) {
return p.concat(c);
}).reduce(function(p, c) {
Object.keys(c).forEach(function(oKey) {
if(p[oKey]) p[oKey].push(c[oKey]);
else p[oKey] = [c[oKey]];
});
return p;
}, {});
This returns the following:
{
"name":["John","Sally","Bob","Lisa"],
"department": ["Math","Science","Law","IT"]
}