2 arrays with json problem (Node.js, Discord.js) - javascript

The first array is:
[
{
id: "megaphone",
name: "Megaphone",
kind: "Consumable",
description: "Unmutes you if you are currently muted",
price: 10,
},
{
id: "expcharge",
name: "Exp Charge",
kind: "Consumable",
description: "Double exp for an hour",
price: 50,
},
{
id: "commonlootbox",
name: "Common Lootbox",
kind: "Consumable",
description: "Chance for a random amount of coins or an item",
price: 1,
},
];
The second part of the JSON I need is into a JSON file.
I tried to add the data of the json like this:
arr.forEach((a) => {
no.push(shop.find((i) => i.id === a.name));
});
And this is perfect, because i get only the data i need.
But the result is that i have two arrays now.
The second is:
[
{ name: "megaphone", quantity: 5 },
{ name: "expcharge", quantity: "3" },
{ name: "commonlootbox", quantity: "3" },
];
Now, what I need to do is basically for Each object in the array, I need to do
"array1.name - array2.quantity (array1.description)"
I need to post it like
Megaphone - 5 (Unmutes you if you are currently muted)
Common Lootbox - 3 (Double exp for an hour)
etc.
Hope this is clear.
Maybe my method is wrong?

well, you need to itirate over the second array and make strings of the result that you want, like so
const secondArray = [
{name: 'megaphone', quantity: 5}
{name: 'expcharge', quantity: '3'}
{name: 'commonlootbox', quantity: '3'}
]
const desiredarray = secondArray.map(item => {
const matchedItem = data.find(({ id }) => id == item.name)
return `${matchedItem.name} - ${item.quantity} (${matchedItem.description})`
});

I think you could store one or both arrays in a Map or directly in an object.
You could try something like this:
obj = array.reduce((obj, element) => {
obj[element.id] = element;
return obj;
}, {});
Now you can iterate one of the arrays and access the corresponding value in the other one directly.

Ciao, you could do something like this:
Solution with array of JSON:
const arr1 = [{id: 'megaphone', name: 'Megaphone', kind: 'Consumable', description: 'Unmutes you if you are currently muted', price: 10},
{id: 'expcharge', name: 'Exp Charge', kind: 'Consumable', description: 'Double exp for an hour', price: 50},
{id: 'commonlootbox', name: 'Common Lootbox', kind: 'Consumable', description: 'Chance for a random amount of coins or an item', price: 1}];
const arr2 = [{name: 'megaphone', quantity: 5},
{name: 'expcharge', quantity: '3'},
{name: 'commonlootbox', quantity: '3'}];
let arr3 = arr1.map(item1 => {
let ok_el = {};
arr2.map(item2 => {
if (item1.id === item2.name) {
ok_el.id = item1.id;
ok_el.name = item1.name;
ok_el.quantity = item2.quantity;
ok_el.description = item1.description;
return ok_el;
}
});
return ok_el;
});
let result = arr3.map(el => {
return el.name + " - " + el.quantity + " (" + el.description + ")";
});
console.log(result);
Solution with JSON of JSONs:
const arr1 = {0:{id: 'megaphone', name: 'Megaphone', kind: 'Consumable', description: 'Unmutes you if you are currently muted', price: 10},
1:{id: 'expcharge', name: 'Exp Charge', kind: 'Consumable', description: 'Double exp for an hour', price: 50},
2:{id: 'commonlootbox', name: 'Common Lootbox', kind: 'Consumable', description: 'Chance for a random amount of coins or an item', price: 1}};
const arr2 = {0:{name: 'megaphone', quantity: 5},
1:{name: 'expcharge', quantity: '3'},
2:{name: 'commonlootbox', quantity: '3'}};
let arr3 = Object.values(arr1).map(item1 => {
let ok_el = {};
Object.values(arr2).map(item2 => {
if (item1.id === item2.name) {
ok_el.id = item1.id;
ok_el.name = item1.name;
ok_el.quantity = item2.quantity;
ok_el.description = item1.description;
return ok_el;
}
});
return ok_el;
});
let result = arr3.map(el => {
return el.name + " - " + el.quantity + " (" + el.description + ")";
});
console.log(result);

Related

find FIRST occurrence of element from Array1 IN Array2, Take the Index that element is found at in Array2, and make a new Array

I have two arrays. look by id, find FIRST occurrence of element from Array1 IN Array2, Take the Index that element is found at in Array2, and make a new Array where element in Array1 is moved to the new index found in Array2. in Array1 {id: 001} is at index 0, I would like it to be in a new Array at index 1 (index it is FIRST found in Array2). {id: 002} is at index 1 in Array1, I would like this to be in the new Array at index 3( index it is FIRST found in Array2) so on....
const Array1 = [
{
id: '001',
school: "blue springs"
},
{
id: '002',
school: "sycamore hills"
},
{
id: '003',
school: "moreland ridge"
},
{
id: '004',
school: "grain valley"
}
]
const Array2 = [
{
id: '003',
participant: "Susan"
},
{
id: '001',
participant: "Henry"
},
{
id: '003',
participant: "Justin" <---- if 003 exists do not duplicate the return array, this is my issue....
},
{
id: '004',
participant: "Jessica"
},
{
id: '002',
participant: "Carly"
},
{
id: '001',
participant: "Chloe" <---- if 001 exists do not duplicate the return array, this is my issue....
}
// got this far,
const finder = Array1.map((el) => { return Array2.findIndex((el2) => { return el2.id === el.id}) })
console.log(finder)
// [ 1, 4, 0, 3 ] <--- need to move Array1 objects to these new indexes
expected output
const Result = [
{
id: '003',
school: "moreland ridge"
},
{
id: '001',
school: "blue springs"
},
{
id: '004',
school: "grain valley"
},
{
id: '002',
school: "sycamore hills"
}
]
You first filter to remove duplicates on Array2, and then look for a match in Array1 regarding id's
const Array1 = [
{
id: '001',
school: "blue springs"
},
{
id: '002',
school: "sycamore hills"
},
{
id: '003',
school: "moreland ridge"
},
{
id: '004',
school: "grain valley"
}
]
const Array2 = [
{
id: '003',
participant: "Susan"
},
{
id: '001',
participant: "Henry"
},
{
id: '003',
participant: "Justin" // <---- if 003 exists do not duplicate the return array, this is my issue....
},
{
id: '004',
participant: "Jessica"
},
{
id: '002',
participant: "Carly"
},
{
id: '001',
participant: "Chloe" // <---- if 001 exists do not duplicate the return array, this is my issue....
}
]
const alreadyShown = {};
const res = Array2.filter( el => {
if (!alreadyShown[el.id]){
alreadyShown[el.id] = true;
return true;
}
return false;
}).map( x => Array1.find( y => x.id === y.id ) || x);
console.log(res)
NOTE: I included a logical OR to provide a fallback case, but this is not defined in OP request
I think you just need to sort the first array by the uniqueness of the identifier in the second array
const Array1 = [{id: '001',school: "blue springs"},{id: '002',school: "sycamore hills"},{id: '003',school: "moreland ridge"},{id: '004',school: "grain valley"}];
const Array2 = [{id: '003',participant: "Susan"},{id: '001',participant: "Henry"},{id: '003',participant: "Justin"},{id: '004',participant: "Jessica"},{id: '002',participant: "Carly"},{id: '001',participant: "Chloe" }];
const idOrder = Array2.map(({ id }) => id).filter((v, i, a) => a.indexOf(v)===i);
console.log('Order:', idOrder );
const sortedByOrder = Array1.sort(({ id: id1 }, { id: id2 }) =>
idOrder.indexOf(id1) - idOrder.indexOf(id2));
console.log('Result:', sortedByOrder);
.as-console-wrapper{min-height: 100%!important; top: 0}

Is there a cleaner way to add a new property with unique values to an array

I'm just learning js now (late to the party I know) and I have the following code and I was wondering if it could be written in a cleaner/simpler way?
Also, ideally, instead of using "if (obj.id === 1)" I would like to iterate through the array and add age based on the sequence i.e. [0] would become '32' and so on.
const students = [ // Three objects, each with four properties
{
id: 1,
name: 'Mark',
profession: 'Developer',
skill: 'JavaScript'
},
{
id: 2,
name: 'Ariel',
profession: 'Developer',
skill: 'HTML'
},
{
id: 3,
name: 'Jason',
profession: 'Designer',
skill: 'CSS'
},
];
const studentsWithAge = students.map(obj => {
if (obj.id === 1) {
return {...obj, age: '32'};
} else if (obj.id === 2) {
return {...obj, age: '26'};
} else if (obj.id === 3) {
return {...obj, age: '28'};
}
return obj;
});
console.log(studentsWithAge);
// output
// [
// {
// id: 1,
// name: 'Mark',
// profession: 'Developer',
// skill: 'JavaScript',
// age: '32'
// },
// {
// id: 2,
// name: 'Ariel',
// profession: 'Developer',
// skill: 'HTML',
// age: '26'
// },
// {
// id: 3,
// name: 'Jason',
// profession: 'Designer',
// skill: 'CSS',
// age: '28'
// }
// ]
You can map the array into the object like so:
const ages = ['32', '26', '28'];
const studentsWithAge = students.map(obj => { ...obj, age: ages[obj.id-1] });
You could create an ages array and use the index to map the value to the corresponding object.
const students = [ // Three objects, each with four properties
{
id: 1,
name: 'Mark',
profession: 'Developer',
skill: 'JavaScript'
},
{
id: 2,
name: 'Ariel',
profession: 'Developer',
skill: 'HTML'
},
{
id: 3,
name: 'Jason',
profession: 'Designer',
skill: 'CSS'
},
];
const ages = [32, 26, 28];
const result = students.map((s, i) => {
return { ...s, age: ages[i] }
});
console.log(result);
Your code is true, another way to add ages by the id is the following code. Just use ids as object key and age as value.
The following code check if id exists in the ages const then add it to the studentsWithAge. It works exactly like your code.
const ages = {1: '32', 2: '26', 3: '28'};
const studentsWithAge = students.map(obj => {
if(ages[obj.id]) obj.age = ages[obj.id];
return obj;
});
But if you're sure all ids have age value simpler code like this could be used:
const ages = {1: '32', 2: '26', 3: '28'};
const studentsWithAge = students.map(obj => ({...obj, age: ages[obj.id]}));
The solution depends on how you store the ages data. Here's an example if you keep the ages data in an array of objects, just like you keep the students data.
This approach is easily extended, you can add any other fields related to the student to the object.
students = [
{id: 1,name: 'Mark',profession: 'Developer',skill: 'JavaScript'},
{id: 2,name: 'Ariel',profession: 'Developer',skill: 'HTML'},
{id: 3,name: 'Jason',profession: 'Designer',skill: 'CSS'}];
extraInfo = [{id: 1, age:32}, {id:2, age: 26}, {id:3, age: 33}];
const result = students.map((s)=>
({ ...s, ...extraInfo.find((a) => a.id === s.id) })
);
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}

Modify object values in an array of objects

I have an array of objects that looks like this:
const arr1 = [
{id: 1, name: 'Dave', tax: 123.34543}
{id: 2, name: 'John', tax: 3243.12323}
{id: 3, name: 'Tom', tax: 122.34324}
]
And I am trying to round off the tax value, so in the end the array should look like this:
[
{id: 1, name: 'Dave', tax: 123.34}
{id: 2, name: 'John', tax: 3243.12}
{id: 3, name: 'Tom', tax: 122.34}
]
I tried using the map function like so:
arr1.map(value => Math.round(value.tax * 100)/100);
but instead of getting a modified array of objects, I get an array with only the result of the Math.round which looks like this:
[ 123.34, 3243.12, 122.34]
How do I map the array of objects to get the expected result as described above.
Thanks.
You can update tax in your map function.
See implementation below.
const arr1 = [
{id: 1, name: 'Dave', tax: '123.34543'},
{id: 2, name: 'John', tax: '3243.12323'},
{id: 3, name: 'Tom', tax: '122.34324'},
];
const taxRoundedArray = arr1.map(item => {
let tax = Math.round(item.tax * 100)/100
return {
...item,
tax
}
});
console.log(taxRoundedArray);
You could map new objects with the wanted values.
const
array = [{ id: 1, name: 'Dave', tax: 123.34543 }, { id: 2, name: 'John', tax: 3243.12323 }, { id: 3, name: 'Tom', tax: 122.34324 }],
result = array.map(o => Object.assign({}, o, { tax: Math.round(o.tax * 100) / 100 }));
console.log(result);
You are very close to the correct solution, see below:
arr1.map(value => {
value.tax = Math.round(value.tax * 100)/100);
return value
});
You need to return the altered object otherwise it gets overwritten.
Hope this helps
Lloyd
Array.map processes the entry in array and return the processed value. In the attempt, you were only returning the updated tax, however, you will need to return the object. Try following
const arr1 = [{id: 1, name: 'Dave', tax: 123.34543},{id: 2, name: 'John', tax: 3243.12323},{id: 3, name: 'Tom', tax: 122.34324}];
const arr2 = arr1.map(({tax, ...rest}) => ({...rest, tax: Math.round(tax * 100)/100}));
console.log(arr2);
map over the array and return each object with a new tax value that has been turned to a floating-point number fixed to two decimal places.
const arr1 = [{"id":1,"name":"Dave","tax":"123.34543"},{"id":2,"name":"John","tax":"3243.12323"},{"id":3,"name":"Tom","tax":"122.34324"}];
const arr2 = arr1.map(obj => {
const tax = +Number.parseFloat(obj.tax).toFixed(2);
return { ...obj, tax };
})
console.log(arr2);
You can do:
const arr1 = [
{id: 1, name: 'Dave', tax: '123.34543'},
{id: 2, name: 'John', tax: '3243.12323'},
{id: 3, name: 'Tom', tax: '122.34324'}
];
const result = arr1.map(user => {
user.tax = (Math.round(+user.tax * 100) / 100);
return user;
});
console.log(result);

filter array of objects from string name to id

I am trying to convert an array of objects containing string values to their id value based off other array of objects. Here are the arrays.
const employees = [
{
name: 'bob',
department: 'sales',
location: 'west'
},
{
name:'fred',
department: 'sales',
location: 'west'
},
{
name:'josh',
department: 'inventory',
location: 'east'
},
{
name: 'mike',
department: 'quality assurance',
location: 'north'
}
];
const departments = [
{
dep: 'sales',
id: 12
},
{
dep:'quality assurance',
id: 11
},
{
dep:'inventory',
id: 13
}
];
const locations = [
{
region: 'west',
id: 3
},
{
region:'north',
id: 1
},
{
region:'east',
id: 2
},
{
region:'south',
id: 4
}
];
I would like the converted employees array to look like this:
[
{name:"bob", department: 12, location: 3},
{name:"fred", department: 12, location: 3},
{name:"josh", department: 13, location: 2},
{name:"mike", department: 11, location: 1}
]
I've tried:
employees.forEach((row) => {
row.department = departments.filter(depart => row.department === depart.dep)
.reduce((accumulator, id) => id)
row.department = row.department.id; // would like to remove this.
});
employees.forEach((row) => {
row.location = locations.filter(loc => row.location === loc.region)
.reduce((accumulator, id) => id);
row.location = row.location.id; // would like to remove this part.
});
I get the desired results from using the forEach I have, but I think there is a better way of using .filter() and .reduce(). I would like help removing the last line of the two forEach statements where I have to set row.department = row.department.id and row.location = row.location.id
One possible approach:
const dehydratedEmployees = employees.map(emp => {
const depId = departments.find(dep => dep.dep === emp.department).id;
const locId = locations.find(loc => loc.location === loc.region).id;
return { name: emp.name, department: depId, location: locId };
});
In other words, you can use Array.prototype.find() instead of filter-reduce combo. As .reduce() won't stop at the first successful search, .find() is both more efficient and concise. Just don't forget to apply polyfill for IE and other non-supportive browsers.
One solution is to create Map for departments and locations to eliminated nested loop when mapping employees.
Map can be created from a nested array: new Map([[key, value], [key, value]]):
const employees = [
{ name: 'bob', department: 'sales', location: 'west' },
{ name:'fred', department: 'sales', location: 'west' },
{ name:'josh', department: 'inventory', location: 'east' },
{ name: 'mike', department: 'quality assurance', location: 'north'}
];
const departments = [
{ dep: 'sales', id: 12 },
{ dep:'quality assurance', id: 11 },
{ dep:'inventory', id: 13}
];
const locations = [
{ region: 'west', id: 3 },
{ region:'north', id: 1},
{ region:'east', id: 2 },
{ region:'south', id: 4}
];
const departmentMap = new Map(departments.map(i => [i.dep, i.id]));
const locationMap = new Map(locations.map(i => [i.region, i.id]));
const result = employees.map(e => ({
name: e.name,
department: departmentMap.get(e.department),
location: locationMap.get(e.location)
}))
console.log(result);
Another possible approach. You can use Array.prototype.filter()(like below)
const employees=[{name:'bob',department:'sales',location:'west'},{name:'fred',department:'sales',location:'west'},{name:'josh',department:'inventory',location:'east'},{name:'mike',department:'quality assurance',location:'north'}];const departments=[{dep:'sales',id:12},{dep:'quality assurance',id:11},{dep:'inventory',id:13}];const locations=[{region:'west',id:3},{region:'north',id:1},{region:'east',id:2},{region:'south',id:4}]
var newArray=employees.map((x)=>{
return { name: x.name,
department: departments.filter(y=>y.dep === x.department)[0].id,
location: locations.filter(y=>y.region===x.location)[0].id};
});
console.log(newArray);

Merging/extend javascript object arrays based on join of a key property in each

I am wanting to merge the following object arrays, by first joining on the id property
var arr1 = [{
id: 1,
name: 'fred',
title: 'boss'
},{
id: 2,
name: 'jim',
title: 'nobody'
},{
id: 3,
name: 'bob',
title: 'dancer'
}];
var arr2 = [{
id: 1,
wage: '300',
rate: 'day'
},{
id: 2,
wage: '10',
rate: 'hour'
},{
id: 3,
wage: '500',
rate: 'week'
}];
So the result would be
[{
id: 1,
name: 'fred',
title: 'boss',
wage: '300',
rate: 'day'
},{
id: 2,
name: 'jim',
title: 'nobody',
wage: '10',
rate: 'hour'
},{
id: 3,
name: 'bob',
title: 'dancer',
wage: '500',
rate: 'week'
}]
I would like to avoid using js frameworks (if possible), although ExtJs is already part of the project.
AT the moment I have a loop with an inner loop that if the keys match it copies the properties and breaks out of the inner loop to start the next outer loop.
Any better suggestions?
Like this?
var combined = [];
function findSecond(id,second){
for (var i=0;i<second.length;i++){
if(second[i].id === id){
return second[i];
}
}
return null
}
while (el = arr1.pop()){
var getSec = findSecond(el.id,arr2);
if (getSec){
for (var l in getSec){
if (!(l in el)) {
el[l] = getSec[l];
}
}
combined.push(el);
}
}
If the arrays have the same length, and the id's are equal, a simpler merge will do:
function merge(a1,a2) {
var i = -1;
while ((i = i+1)<a1.length) {
for (var l in a2[i]) {
if (!(l in a1[i] )) {
a1[i][l] = a2[i][l];
}
}
}
return a1;
}
Here's a working example
[Edit 2016/07/30] Added a snippet using more functional approach and, based on #djangos comment, an extra method to combine both arrays.
(function() {
var alert = function(str) {document.querySelector('#result').textContent += str + '\n';};
var arrays = getArrays();
alert('Combine on id (shared id\'s):')
alert(JSON.stringify(combineById(arrays.arr1, arrays.arr2), null, ' '));
alert('\nCombine on id (all id\'s):')
alert(JSON.stringify(combineBothById(arrays.arr1, arrays.arr2), null, ' '));
// for combineBothById the parameter order isn't relevant
alert('\nCombine on id (all id\'s, demo parameter order not relevant):')
alert(JSON.stringify(combineBothById(arrays.arr2, arrays.arr1), null, ' '));
// combine first array with second on common id's
function combineById(arr1, arr2) {
return arr1.map(
function (el) {
var findInB = this.filter(function (x) {return x.id === el.id;});
if (findInB.length) {
var current = findInB[0];
for (var l in current) {
if (!el[l]) {el[l] = current[l];}
}
}
return el;
}, arr2);
}
// combine first array with second on all id's
function combineBothById(arr1, arr2) {
var combined = arr1.map(
function (el) {
var findInB = this.filter(function (x) {return x.id === el.id;});
if (findInB.length) {
var current = findInB[0];
for (var l in current) {
if (!el[l]) {el[l] = current[l];}
}
}
return el;
}, arr2);
combined = combined.concat(arr2.filter(
function (el) {
return !this.filter(function (x) {return x.id === el.id;}).length;
}, combined));
return combined;
}
function getArrays() {
return {
arr1: [{
id: 1,
name: 'fred',
title: 'boss'
}, {
id: 2,
name: 'jim',
title: 'nobody'
}, {
id: 3,
name: 'bob',
title: 'dancer'
}],
arr2: [{
id: 1,
wage: '300',
rate: 'day'
}, {
id: 2,
wage: '10',
rate: 'hour'
}, {
id: 4,
wage: '500',
rate: 'week'
}]
};
}
}());
<pre id="result"></pre>
You can merge two arrays by id column with Alasql library:
var res = alasql('SELECT * FROM ? arr1 JOIN ? arr2 USING id', [arr1,arr2]);
Try this example at jsFiddle.
try this...
var arr1 = [{
id: 1,
name: 'fred',
title: 'boss'
},{
id: 2,
name: 'jim',
title: 'nobody'
},{
id: 3,
name: 'bob',
title: 'dancer'
}];
var arr2 = [{
id: 1,
wage: '300',
rate: 'day'
},{
id: 2,
wage: '10',
rate: 'hour'
},{
id: 3,
wage: '500',
rate: 'week'
}];
let arr5 = arr1.map((item, i) => Object.assign({}, item, arr2[i]));
console.log(arr5)

Categories

Resources