pushing js object to an arrays - javascript

I am working a demo react project, and got stuck to pick name and value of js object and push to an array. which I want to use for queryparams. The js objects looks as follow
const ingredient = [
{ salad: 0, bacon: 0 },
{ cheese: 0, meat: 0 }
]
here I want the key and the value to push to an array. ex.
const arrays = []
I try this way and did not got it correct.
=> for (let name of ingredient){
arrays.push(name + ingredient[name])
}
=> arrays
(2) ["[object Object]undefined", "[object Object]undefined"]
how do I push only the name and value correctly so I will able to use them in the url?
thanks in advance for your help.

First you have a struct problem:
Instead of
const ingredient = [
{ salad: 0, bacon: 0 },
{ cheese: 0, meat: 0 }
]
you should have
const ingredient = { salad: 0, bacon: 0, cheese: 0, meat: 0 }
or
const ingredient = [{salade:0}, {bacon:0}, {cheese:0}, {meat:0}]
Let's say you keep only an object:
const ingredient = { salad: 2, bacon: 3, cheese: 4, meat: 0 }
let toQuery = function(obj, is_str) {
let arr = Object.keys(obj).reduce((acc, key) => {
acc.push(key+"="+obj[key]);
return acc
}, [])
return is_str ? "?" + arr.join('&') : arr
}
console.log(toQuery(ingredient, false))
console.log(toQuery(ingredient, true))
Now make it works with your object (example, multi recipe)
const ingredient = [{ salad: 2, bacon: 3}, {cheese: 4, meat: 0 }]
let toQuery = function(obj, to_str) {
let arr = []
obj.forEach(o => {
Object.keys(o).forEach(k => {
arr.push(k+"="+o[k])
})
})
return to_str ? "?" + arr.join('&') : arr
}
console.log(toQuery(ingredient, false))
console.log(toQuery(ingredient, true))

Try this:
ingredient.forEach((elem) =>
{
for(key in elem)
{
arrays.push(`${key}, ${elem[key]}`);
}
});

If name you mentioned is the key of object item. you can try this.
const ingredient = [
{ salad: 0, bacon: 0 },
{ cheese: 0, meat: 0 }
]
const rs = ingredient.reduce((acc, e) =>{
for(let key in e) {
acc.push(`${key}: ${e[key]}`)
}
return acc
}, [])
console.log(rs)

Related

Sort a Json by user.id from a JSON

I have a JSON in which I save the GuildID and then again the UserID
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
Now I want to sort the users by XPIns from one Guild. I remember this code part here
let obj;
fs.readFile('./xpdata.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data)
var sorted = Object.entries(obj).sort((a, b) => b[1] - a[1])
});
In the end, the user with more should be in the 1st position (866935358448468008). Can anyone help me?
I've seen a similar question before but couldn't get it to work if there was a GuildID in front of it
The code I had done before (sorry for the sloppy code that was a year ago (Code is updated)):
let obj;
fs.readFile('./userdata.json', 'utf8', function (err, data) {
if (err) throw err;
try {
obj = JSON.parse(data)
} catch (error) {
if(error) return console.log("Ein Fehler ist aufgetreten! " + error);
}
var sorted = Object.entries(obj).sort((a, b) => b[1].Economy.Balance - a[1].Economy.Balance)
if(sorted.length > 10) sorted = sorted.slice(0, 10)
var lBString = "";
var s = 1;
sorted.forEach(user => {
let usertag = Data[user[0]].Tag
lBString += `${s}. ${usertag} • **${user[1].Economy.Balance}$**\n`
s = s += 1
})
let embed = {
title: `Leaderboard Balance`,
description: lBString,
color: 0xFFFF00,
thumbnail: {
url: client.user.avatarURL(),
},
timestamp: new Date(),
footer: {
text: footer,
icon_url: client.user.avatarURL(),
},
}
e.reply({embeds: [embed]});
});
If you simply want the highest ranking user in terms of "XPIns", I suggest you use a Array.reduce() call on the entries of the inner object.
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
const topUser = Object.entries(data['385524088980111362']).reduce((acc, cur) => (
acc[1]?.XPIns > cur[1]?.XPIns ? acc : cur
), []);
console.log(topUser);
What I do in cases like this is to use another object as index using a reference of the main array/object
ie:
var index = {};
// replace .id with the attribute you want to use. In your case XPins
index[ object.id ] = main_index_reference;
once you have generated the index, then you can get the keys using Object.keys( index ):
var keys = Object.keys( index );
keys.forEach( function( key ){
var element = main_object[ key ];
// do whatever with the element
} );
Your main_object remains unchanged. In your particular case you want the highest value, all you need to do is to extract the last element from the keys array.
You can try with this. However, the users do not have their ID inside their object, so you'd probably have to patch the ID before sorting.
const data = {
// if the guild could have list of users then it would have been much better
// instead of Object list with ID, Array of objects with ID in it works much faster..
"385524088980111362": {
"672748733737467936": {
// if we had user ID here, then it would have been better
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
};
function getSortedUsersByXPins(data, guildId) {
// if guild has array of users, then we won't need Object.values
const sorted = Object.values(data[guildId]).sort((user1, user2) => {
return user2.XPins - user1.XPins
});
return sorted;
}
const sorted = getSortedUsersByXPins(data, '385524088980111362');
console.log(sorted)
You can try it with this solution, in case you want to convert the object to a list. The main issue is the missing identifier if you work with a list.
This assumes that you would use a function like Object.entries before to convert it.
My recommendation: Include the id into the object and convert it to a list.
let guildList = [
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2,
"Id": "672748733737467936"
},
{
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7,
"Id": "866935358448468008"
}
];
let aSorted = guildList.sort((a, b) => b.XPIns-a.XPIns)
console.log(aSorted)
Just extract the player objects and sort them, pretty much the way you already described ((p1, p2) => p2.XPIns - p1.XPIns).
Here is an example:
const data = {
"385524088980111362": {
"672748733737467936": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 2
},
"866935358448468008": {
"XP": 0,
"Level": 1,
"BisLevel": 100,
"NächsteXP": 0,
"XPIns": 7
}
}
}
const res = Object.fromEntries(Object.entries(data).map( ([gid, users]) => [gid, Object.entries(users).map(([id, u]) => ({id, ...u })).sort( (u1, u2) => u2.XPIns - u1.XPIns)] ))
console.log(res)
Note that you cannot create an object with player id as key without losing the order, since JS objects always put numeric keys in ascending order.

Comparing property of object with property of another array

I am having difficulty comparing properties of two objects/arrays
First object
{
"62ac1c8d5b25ad28781a586d": {
"selectedOption": 0
},
"62ac1c8d5b25ad28781a586e": {
"selectedOption": 0
}}
Second Array
[
{
"question_id": "62ac1c8d5b25ad28781a586d",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586e",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586f",
"ans": 0
}
]
Kindly suggest how to compare the initial property of first object(example: 62ac1c8d5b25ad28781a586d) with the question_id property of second array and return only the matching question_id
You can filter elements from secondArr using Set as:
const obj = {
'62ac1c8d5b25ad28781a586d': {
selectedOption: 0,
},
'62ac1c8d5b25ad28781a586e': {
selectedOption: 0,
},
};
const secondArr = [
{
question_id: '62ac1c8d5b25ad28781a586d',
selected_ans: 0,
},
{
question_id: '62ac1c8d5b25ad28781a586e',
selected_ans: 0,
},
{
question_id: '62ac1c8d5b25ad28781a586f',
ans: 0,
},
];
const keys = new Set(Object.keys(obj));
const result = secondArr.filter((o) => keys.has(o.question_id));
console.log(result);
You could simply use the find method defined on the array prototype.
function compare(id, arr){
return arr.find(arrObj => arrObj.question_id === id);
}
To find all the matching ids from the object present in the array, you could loop through the keys and call the compare function for those keys like this.
function compare(id, arr) {
return arr.find(arrObj => arrObj.question_id === id);
}
const obj = {
"62ac1c8d5b25ad28781a586d": {
"selectedOption": 0
},
"62ac1c8d5b25ad28781a586e": {
"selectedOption": 0
}
}
const arr = [
{
"question_id": "62ac1c8d5b25ad28781a586d",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586e",
"selected_ans": 0
},
{
"question_id": "62ac1c8d5b25ad28781a586f",
"ans": 0
}
]
const matchingObjects = [];
for (let key in obj) {
const matchObject = compare(key, arr);
if (matchObject) {
matchingObjects.push(matchObject);
}
}
console.log(matchingObjects);

How to compare two arrays and return another one?

How to compare two arrays and return another one?
I'm trying to compare two arrays to compare records by id and then render a new array
const arr1 = [
{ id: 1, title: "Admin" },
{ id: 2, title: "Vip" }
];
const arr2 = [
{
id: 1,
root: 1
},
{
id: 2,
root: 0
}
];
let intersection = arr1.filter(({ id }) => arr2.includes(id));
need:
const needArr = [
{ id: 1, title: "Admin", root: 1 },
{ id: 2, title: "Vip", root: 0 }
];
You could make use of map() and find() and iterate over the first array arr1:
const needArr = arr1.map(entry => {
const root = arr2.find(arr2Entry => entry.id === arr2Entry.id)?.root
return {...entry, root: root}
} )
The root property will be set to undefined for each entry in the needArr result if there is no entry with the same id in arr2 as in arr1.
Something like this could work,
const giveNew = (a, b) => {
let shorter, longer;
if(a.length>b.length){
longer = a;
shorter = b;
} else {
longer = b;
shorter = a;
}
return longer.map((v, i)=> {
const matched = shorter.find(val=> val.id === v.id);
if(matched){
return {
...v, ...matched
}
}
})
}
Assuming there's a 1:1 relationship between the arrays - map over one of the arrays, find the corresponding object in the other array by its id, and then return a new updated object.
const arr1=[{id:1,title:"Admin"},{id:2,title:"Vip"}],arr2=[{id:1,root:1},{id:2,root:0}];
const out = arr2.map(obj => {
return {
...arr1.find(inner => inner.id === obj.id),
root: obj.root
};
});
console.log(out);
As is pointed out in Merge two array of objects based on a key, you can do this:
let intersection = arr1.map(item => ({...item, ...arr2.find(item2 => item.id === item2.id)}));
I tried this worked.
const arr1 = [
{ id: 1, title: "Admin" },
{ id: 2, title: "Vip"}
];
const arr2 = [
{
id: 1,
root: 1
},
{
id: 2,
root: 0
}
];
for(var i=0 ;i < arr2.length; i++)
{
objIndex = arr1.findIndex((obj => obj.id == arr2[i].id));
arr1[objIndex].root = arr2[i].root;
}
console.log(arr1);
Hope this satisfies your use case. This also works in the case where there is no 1:1 mappings.
const arr1 = [
{ id: 1, title: "Admin" , root: 0 },
{ id: 2, title: "Vip" , root: 0 },
{ id: 100, title: "NotExistInArr2" , root: 0 }
];
const arr2 = [
{
id: 1,
root: 1
},
{
id: 2,
root: 0
},
{
id: 200,
root: 0
}
];
const consolidatedIds = arr1.map(a => a.id).concat(arr2.map(a => a.id));
//console.log(consolidatedIds);
const consolidatedDedupedIds = arrayUnique(consolidatedIds);
//console.log(consolidatedDedupedIds);
const needArr = consolidatedDedupedIds.map(entry => {
const arr1Item = arr1.find(arr1Entry => entry === arr1Entry.id);
const arr2Item = arr2.find(arr2Entry => entry === arr2Entry.id);
return {...arr1Item, ...arr2Item}
} )
console.log(needArr)
//--- utility function
function arrayUnique(array) {
var a = array.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
Note: improvised version of other questions, inspired from other answers

Extract from array of objects some properties

How can I extract from an array of objects some properties like without for loop, with map or filter?
Example:
obj = [
{ 'cars' : 15, 'boats' : 1, 'smt' : 0 },
{ 'cars' : 25, 'boats' : 11, 'smt' : 0 }
]
extractFunction(obj, ['cars' , 'boats']) -> { 'cars' : [15,25], 'boats' : [1,11]}
You can do it with reduce:
* As you can see, the benefit of this approach (according to the other answers) is that you loop the keys only one time.
const extractFunction = (items, keys) => {
return items.reduce((a, value) => {
keys.forEach(key => {
// Before pushing items to the key, make sure the key exist
if (! a[key]) a[key] = []
a[key].push(value[key])
})
return a
}, {} )
}
obj = [
{ 'cars' : 15, 'boats' : 1, 'smt' : 0 },
{ 'cars' : 25, 'boats' : 11, 'smt' : 0 }
]
console.log(extractFunction(obj, ['cars', 'boats']))
You could take a dynamic approach by using the keys for mapping the values.
function extractFunction(array, keys) {
return array.reduce(
(r, o) => (keys.forEach(k => r[k].push(o[k])), r),
Object.assign(...keys.map(k => ({ [k]: [] })))
);
}
console.log(extractFunction([{ cars: 15, boats: 1, smt: 0 }, { cars: 25, boats: 11, smt: 0 }], ['cars', 'boats']));

Create a new object using keys and values from another object

I'm saving an object in state that looks like:
ingredients: {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
}
I want to use this in my component's state as follows
ingredients: {
salad: 3,
cheese: 2
}
I used Object.keys and map at first but it returns an Array of key value pairs instead of objects.
Although this works:
const newIngredientsObject = {};
for (const i in ingredientsObject)
newIngredientsObject[i] = ingredientsObject[i].amount;
return newIngredientsObject;
I want to find a solution without a helper method, as such:
const mapStateToProps = state => {
return {
ingredients: Object.keys(state.burger.ingredients).map(i => (
{ [i]: state.burger.ingredients[i].amount } )),
totalPrice: state.burger.totalPrice
}
};
You could map the entries of the object by using the amount property of the values and take Object.assign for getting a new object.
var ingredients = { salad: { amount: 3, basePrice: 1 }, cheese: { amount: 2, basePrice: 1.2 } },
result = Object.assign(
...Object.entries(ingredients).map(([key, value]) => ({ [key]: value.amount }))
);
console.log(result);
when you want to create one object to inside to another go this web
object 1 = {
content 1 = {
stuff = {
},
more Stuff = {
}
}
}
object 2 = {
key 1:"",
key 2:""
}
object 1.content 1 = object 2;
You asked a solution with Object.keys, here is one:
var x = {ingredients: {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
}}
Object.keys(x.ingredients).map((d,i)=>[d,x.ingredients[d].amount]).reduce((ac,d,i)=>(ac[d[0]]=d[1],ac),{})
//{salad: 3, cheese: 2}
The shortest I could come up with it using Object.keys and reduce
const ingredients = {
salad: {
amount: 3,
basePrice: 1
},
cheese: {
amount: 2,
basePrice: 1.2
}
};
let newObject = Object.keys(ingredients).reduce((acc, val) => {
acc[val] = ingredients[val].amount;
return acc;
}, {});
console.log(newObject);
ANSWER:
Thanks for the solutions provided by #ibowankenobi and #Nina Scholz
Reduce function:
Object.keys(ingredients)
.map( (d, i) => [d, ingredients[d].amount])
.reduce( (ac, d, i) => (ac[d[0]] = d[1], ac), {} );
Entries function:
Object.assign(...Object.entries(ingredients)
.map( ([key, value]) => ({ [key]: value.amount }) ) );
reduce: 0.0849609375ms
entries: 0.1650390625ms
forLoop: 0.07421875ms
reduce: 0.024169921875ms
entries: 0.048095703125ms
forLoop: 0.010009765625ms
reduce: 0.010009765625ms
entries: 0.016845703125ms
forLoop: 0.0078125ms
After some testing, it seems like using a for loop is the most efficient and after that the reduce function.

Categories