How to create a new array from multiple arrays - javascript

I'm trying to somewhat combine 3 arrays to create a new one. So the end result is
<li>array1[0]array2[0]array3[0]</li>
I tried a for loop but it ends up with 27 answers and there should only be 2 with the data I have.
// const ingredientsList = () => {
// for (let i = 0; i < recipe.ingredients.length; i++) {
// for (let j = 0; j < recipe.size.length; j++) {
// for (let k = 0; k < recipe.amount.length; k++) {
// console.log(recipe.amount[k], recipe.size[j], recipe.ingredients[i]);
// <li>
// {recipe.amount[k]}
// {recipe.size[j]}
// {recipe.ingredients[i]}
// </li>;
// }
// }
// }
// };
I would greatly appreciate anyone's help. I'm currently working in reactjs. Each array is the same length. I have 3 arrays: ingredient list, amount, and size. So I want to combine them so they read smoothly such as "1 cup flour"

The way you are looping through the three arrays will end up as such (in pseudo code):
Loop through the first array and for every element:
Loop through the second array and for every element:
Loop through the third array and
for every element create a list item of each element at index n from
each array.
Since I am not sure exactly what you are wanting I will have to assume they are the same length arrays so you can do:
for(let i = 0; i < recipe.amount.length; i++) {
console.log(`${recipe.amount[i]} ${recipe.size[i]} ${recipe.ingeredients[i]}`)
}
This should get you logging the appropriate results, then just create the html list elements.

If I understand correctly based on the code in the question, you have three arrays (ingredients, size, amount).
If each of the arrays is the same length and each index's data corresponds to the data at the same index of the others, you could write a loop using the length of one of them and pass the same index into each array like...
for (let i = 0; i < recipe.ingredients.length; i++) {
console.log(
recipe.ingredients[i],
recipe.size[i],
recipe.amount[i],
);
}
Seeing as you're working in react though, if you have control over the data yourself, it would probably make more sense to store each instruction in an object in a recipe array, then map over that array and create the list item like...
Somewhere in the component could be something like...
this.recipe = [
{
ingredient: 'something',
amount: 'some amount',
size: 'some size',
},
{
ingredient: 'something',
amount: 'some amount',
size: 'some size',
},{
ingredient: 'something',
amount: 'some amount',
size: 'some size',
}
]
and in the template...
{
recipe.map((instruction) => (
<li>
{ instruction.amount }
{ instruction.size }
{ instruction.ingredient }
</li>
));
}

const emp1 = ["Cecilie", "Lone"];
const emp2 = ["Emil", "Tobias", "Linus"];
const allEmp = emp1.concat(emp2);
you can try using concat keyword to merge arrays. In case of more than two arrays you can use
emp3 = ["john", "lacy"]
const allEmp = emp1.concat(emp2, emp3);

Related

How can I Merge an array of objects

I was wondering how i could merge these two objects retrieve the tag values and store them in an array. This data is also coming from a json response so incoming data should be pushed onto the end of the new array.
so it would look something like this
["2011 LDI", "2012 LDI"]
array with incoming data:
["2011 LDI", "2012 LDI","2013 LDI"]
Here is what I am getting back in my console.log:
[19-08-25 21:58:32:055 PDT] []
[19-08-25 21:58:32:056 PDT] []
Here are the two objects of arrays i am trying to merge:
{date_added=2019-08-26 04:19:00.112083, tag=LDI 2011}
{date_added=2019-08-26 04:19:00.112089, tag=LDI 2012}
and I want it to look like this
[LDI 2011, LDI 2012]
and how I am trying to do it.
var tagtest = [];
var tags = message.student_detail.student_tags,
i = 0,
len = tags.length;
for (i; i < len; i++) {
var obj = tags[i];
for (a in obj) {
}
Array.prototype.push(tags, tagtest);
Logger.log(tagtest)
}
Based on your desired output ([LDI 2011, LDI 2012]), You may want the only tag values from the array, If this is what you are looking for then .map() will help you
const array = [
{
date_added: '2019-08-26',
tag: 'LDI 2011'
},
{
date_added: '2019-08-26',
tag: 'LDI 2012'
}];
const tags = array.map((r) => {
const chunk = r.tag.split(' ');
return `${chunk[1]} ${chunk[0]}`;
} );
console.log(tags);
A for in loop is a great way to work with objects. I updated the code above so that it was actually an array of objects, not an error. See below :)
var data = [{date_added: "2019-08-26 04:19:00.112083", tag: "LDI 2011"},
{date_added: "2019-08-26 04:19:00.112089", tag: "LDI 2012"}];
var newArr = [];
for(var item in data) {
newArr.push(data[item].tag);
}
console.log(newArr);

how to iterate over multiple arrays of parameters

I want to iterate over the arrays and pass the values as parameters to the method.
function getAll() {
urls = [contactUrl, accountUrl, assestUrl];
nodes = ['#contactData', '#accountData', '#assetData'];
list = [$noContacts, $noAccounts, $noAsset];
//Todo
search(url, node, list);
}
e.g.: in first iteration: search(contactUrl, '#contactdata', $noContacts)
What is the best way to handle this ?
You could just go the simple way:
for (let i = 0; i < urls.length; i++) {
search(urls[i], nodes[i], list[i]);
}
Of course, that considers your arrays are of the same length. If you want to go as far as your shortest array, you could also do:
const len = Math.min(urls.length, nodes.length, list.length);
And then iterate until i < len.
Assuming all the arrays are the same length:
urls.forEach((url, index) => {
search(url, nodes[index], list[index]);
});
I guess you would want an array of search result returned back. In this case you can use map function like this
function getAll() {
urls = [contactUrl, accountUrl, assestUrl];
nodes = ['#contactData', '#accountData', '#assetData'];
list = [$noContacts, $noAccounts, $noAsset];
return [...urls.map((url, index) => search(url, nodex(index), list[index]))]
}
You can go the simple iteration route as other answers mention. However, that requires the arrays to all be the same length, but more importantly, this seems like the perfect opportunity to refactor a bit. If these three arrays are so tightly coupled and correlated by index, perhaps they should be turned into a single array of objects instead?
function getAll() {
let searches = [
{ url: contactUrl, node: '#contactData', list: $noContacts },
{ url: accountUrl, node: '#accountData', list: $noAccounts },
{ url: assetUrl, node: '#assetData', list: $noAsset },
];
searches.forEach(item => {
search(item.url, item.node, item.list);
});
}

Nested foreach/forloops, looping through JSON to extract values

I'm going to pre-face this with saying i'm not sure this is the best approach so other approaches are greatly appreciated
End Goal: To store a list of products and the toppings purchased by calling the woocommerce API and using the response data
I'm calling the woocommerce REST api that provides me a good chunk of JSON data back. In the JSON are line_items. These are the products purchased. Nested in line_items are meta_data, this is the toppings for example tomato or sauce.
Attached an image of the JSON
So what i'm trying to do is create something like this
var testOrderItems =
[{
title: "Fried Chicken Burger",
meta: [
"Lettuce",
"cheese slice",
"kethcup"
]
},
{
title: "Beef Burger",
meta: [
"Lettuce",
"cheese slice",
"kethcup"
]
}
]
which will follow my schema for oder items
var orderItems = new Schema({
title: {type: String, required: true},
meta: [{type: String}]
});
So to do this, i figured I would just do a forloop or foreach through the JSON to get all the product names and their meta. Getting actual values is easy. The hard part is creating the array or JSON object that I can then store, i'm just not sure how to create it whilst in the loop. Below are a few things I tried
let fullData = JSON.parse(result)
//parsed response from woocommerce API call
fullData.line_items.forEach((product, index) => {
//for each line item get me the product
orderItems.push(product.name)
//var namey =
//push the product name to the orderItemsArray
product.meta_data.forEach(function(meta) {
//checks for string as one of the plug-ins fills the meta with more nested information and we only want the top level string
if (typeof meta.value === 'string' || meta.value instanceof String)
// it's a string
orderItems.push(meta.value)
//Onbviously won't nest the meta with the product name just on new lines
})
});
The I thought I could do it in for loops by storing an ID ref as "i" and being able to re-reference this later in the nested loop to add the meta, i got a little lost with this
var length = fullData.line_items.length
for (let i = 0; i < length; i++) {
// console.log(i);
console.log(fullData.line_items[i].name)
for (let j = 0; j < fullData.line_items[i].meta_data.length; j++) {
var metaValue = fullData.line_items[i].meta_data[j].value
if (typeof metaValue === 'string' || metaValue instanceof String) {
console.log(fullData.line_items[i].meta_data[j].value);
stringMeta = fullData.line_items[i].meta_data[j].value
//this works but has drawbacks
//1 obviously just overwrites itself each time
//2 will stop at the end of meta so won't add items without meta
finalOrderItems = {
id: i,
name: fullData.line_items[i].name,
meta: [stringMeta]
}
}
}
}
and thats where I am, feels like this should be incredibly easy but can't quite grasp it at the moment.
You could simply create the object that represents your schema first, then return it from a map of your json Object. So, it would look like the following:
let testOrderItems = fullData.line_items.map((product)=>{
let obj = { name: product.name };
obj.meta = product.meta_data.map((meta)=>{
if (typeof meta.value === 'string' || meta.value instanceof String)
return meta.value;
}).filter((value)=>!!value);
return obj;
})
console.log(testOrderItems);
Although, the if statement seems a little redundant, since the woocommerce api will simply either have meta or not. However, you may have some plugin or something which is adding more information to the meta area so i've kept it in my example.
This looks like a job for map and reduce not forEach. map will map each object of line_items into a new object and reduce will group and organize the metas by key for each object:
var orderItems = fullData.line_items.map(function(product) { // map each product in line_items
return { // into a new object
title: product.name, // with title equals to the current product's name
meta: product.meta_data.reduce(function(acc, meta) { // and metas accumulated from each meta object in the current product's meta_data array
acc[meta.key] = acc[meta.key] || []; // first, check if there is an array for the current meta's key in the group object 'acc', if not create one
acc[meta.key].push(meta.value); // add the current meta's value to that array
return acc;
}, {})
}
});
Shorter using arrow functions:
var orderItems = fullData.line_items.map(product => ({
title: product.name,
meta: product.meta_data.reduce((acc, meta) => {
acc[meta.key] = acc[meta.key] || [];
acc[meta.key].push(meta.value);
return acc;
}, {})
}));

JavaScript nested for-loop to add values to an object

I have encountered a situation in my code where I have three java script variables in which two are arrays and one is a single string variable. The following are their structure:
var selectedUser = $('#Employees_SelectedValue').val(); //It has one one value "12121"
var selectedCountries = $('#Countries_SelectedValue').val(); //It has multiple values ["IND", "USA"]
var selectedSourceSystems = $('#SourceSystems_SelectedValue').val(); //It has multiple values ["SQL", "ORACLE", "MySQL"]
What I have to do is to add these values in a class on the basis of selectedUser such as User is same for all the values but the remaining two are different as:
var userSettings = { userName: selectedUser, userCountry: selectedCountries, userSourceSystem: selectedSourceSystems };
The situation is to add the values from this class into an array in such a way that every userCountry and userSourceSystem will come as a single entity such as:
{ userName: "12121", userCountry: "IND", userSourceSystem: "SQL" },
{ userName: "12121", userCountry: "USA", userSourceSystem: "ORACLE" },
{ userName: "12121", userCountry: "", userSourceSystem: "MySQL" }
I'm trying the approach of nested-for loop to handle this scenario like:
for (var i = 0; i < selectedCountries; i++)
{
for (var j = 0; j < selectedSourceSystems; j++)
{
userSettings.userName = selectedUser;
//Add i and j values
}
}
Please suggest an effective approach other than this.
You may set up a 3×n matrix ( a 2d array) and rotate it by 90 degrees:
var matrix = [[selectedUser],selectedCountries,selectedSourceSystems];
var result =
Array(//set up a new array
matrix.reduce((l,row)=>Math.max(l,row.length),0)//get the longest row length
).fill(0)
.map((_,x)=> matrix.map((row,i) => row[i?x:x%row.length] || ""));
Result
If result should contain objects, then map the 2d array to objects:
var objects = result.map(([a,b,c])=>({userName:a,userCountry:b,userSourceSystem:c}));
result
Small explanation:
row[i?x:x%row.length] || ""
Actually does the following:
If were in the first row ( i=0 ) ("12121")
take whatever value of the array (x%row.length), so basically always "12121"
if not, try to get the value of the current column(x)
if row[x] doesnt exist (||) take an empty string ("")
A more basic approach:
var result = [];
for(var i = 0,max = Math.max(selectedCountries.length,selectedSourceSystems.length);i<max;i++){
result.push({
userName:selectedUser,
userCountry:selectedCountries[i]||"",
userSourceSystem:selectedSourceSystems[i]||""
});
}
result
I believe it would be better to restructure your userSettings object in more natural way:
userSettings: {
name: "userName",
countries: ["USA", "IND"],
userSourceSystems: ["MySQL", "Oracle"]
}
Then you can fill it with settings from your inputs like this
for (item in selectedCountries)
userSettings.countries.push(item)
for (item in selectedCountries)
userSettings.userSourceSystems.push(item)

Get all string values from a nested object

I have an object, with nested objects. How do I target a specific index of the object and loop through all the nested values of image. As you will note the length of the nested objects vary.
Target example: productArray[0].image = test1.png, test2.png, test3.png
var products = [
//item1
{
identifier: "item-0",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png"
}
},
//item2
{
identifier: "item-1",
image: {
"img1": "test1.png",
"img2": "test2.png"
}
},
//item3
{
identifier: "item-2",
image: {
"img1": "test1.png",
"img2": "test2.png",
"img3": "test3.png",
"img4": "test4.png",
"img5": "test5.png",
"img6": "test6.png",
"img7": "test7.png"
}
}
];
We can do this. What you need to do is a simple loop through the object at a specific index, or you can target them all. Note that the image object is not an array, so it will not have an accurate length property.
Target all indexes:
for(var i = 0; i < products.length; i++) {
console.log("Item: " + i);
var images = products[i].image;
for(var a in images)
console.log(images[a]);
}
Target specific:
for(var i in products[0].image)
console.log(products[0].image[i]);
I used a for loop here, but you can use a while loop if you would like.
example
Steps:
You need to iterate over your original array of products. products
Each element (product) will be in format { identifier: "", image : {"img1" : "img2", ..}} products[i]
You get the image property of current product - this is an object. products[i].image
Now you need to iterate over the properties of the image object. products[i].image[j]
Code:
for(var i = 0; i < products.length; i++)
{
for(var j in products[i].image)
{
// Here you have all the images for the current product.
// You can print them, group them or whatever you want to do with them
console.log(products[i].image[j]);
}
}
Also you can change the code (introduce variables) to be more readable.
var strs = (function( obj ) {
var ret = [];
for( im in obj ) {
ret.push( obj[im] );
//You could access each image URL here
//ad strs in the end will have all of them
//comma-separated after this code completes
// im is the key, obj[ im ] the value
}
return ret.join(',');
})( products[0].image );
console.log( strs );
WORKING JS FIDDLE DEMO
Here is another way of doing this, with newer functions in ECMAScript 5
var images = Object.keys(products[2].image).map(function(key){
return products[2].image[key]
})
console.log(images) // Returns: ["test1.png", "test2.png", "test3.png", "test4.png", "test5.png", "test6.png", "test7.png"]
How It Works:
Object#keys returns an array of key names. Array#map creates a new array using the keys from Object#keys. By looking up the key from the object you get the value, which will be the image name.
JS FIDDLE

Categories