Convert arrays to values (with keys!) in an array of objects - javascript

I scoured lots of posts for turning arrays into objects and it looks like there are A LOT of posts doing the reverse of what I'd like. If this is redundant with another post I'd like to see what the title is since I really struggled to find it!
I have two arrays:
let x = [1,2,3]
let y = ["a", "b", "c"]
I want to create an array of objects with keys so that the resulting array looks like:
data = [
{x: 1, y: "a"},
{x: 2, y: "b"},
{x: 3, y: "c"}
]
I tried Object.assign and some other methods but am still struggling (and I'd also like to know what key words I should have used to search if this is already posted since I couldn't find it). Any help appreciated!

You could do that using map with index
let x = [1, 2, 3];
let y = ["a", "b", "c"];
const res = x.map((el, i) => ({ x: el, y: y[i] }));
console.log(res);

Why not use a simple for loop
let x = [1,2,3]
let y = ["a", "b", "c"]
let data = [];
for(let i = 0 ; i < x.length; i++){
data.push({x:x[i],y:y[i]});
}

Related

Is it possible to using forEach method for two arrays in same time?

var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
Let's assume that I want to create a list like
1 a
2 b
3 c
4 d
5 e
by using template literal.
let x;
x = document.createElement('li');
x.innerHTML += `<span>${<arr1 index>}</span> <span>${<arr2 index>}</span>`
How can I do that ? Can we use forEach for two arrays in same time ?
This would be more like flatten(zip(arr1, arr2)). There is no built-in zip though you can very easily make it and you can see Array.flat here: MDN: Array.flat.
const arr1 = [1, 2, 3, 4, 5];
const arr2 = ["a", "b", "c", "d", "e"];
const flatten = arr => arr.flat();
const zip = (a, b) => a.map((e, idx) => [e, b[idx]]);
const arr3 = flatten(zip(arr1, arr2));
console.log(arr3);
The answer is "kind of." What you can do is loop through one array with a forEach method, and use the optional argument index to get the value of the second array as well. Something like this:
var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
arr1.forEach((value, index) => {
console.log(value);
console.log(arr2[index])
})
But if the data in the two arrays are at all related, you'd want to put the data in the same object, like this:
var arr = [
{
num: 1,
letter: "a"
},
{
num: 2,
letter: "b"
},
{
num: 3,
letter: "c"
}
];
arr.forEach(value => {
console.log(value.num);
console.log(value.letter);
})
Or you would want to use a regular for loop
You could simply use a for() loop instead:
const max = Math.max(arrA.length, arrB.length)
for (let i = 0; i < max; i++) {
const objA = arrA[i],
objB = arrB[i]
if ('undefined' !== typeof objA) {
console.log({ objA })
}
if ('undefined' !== typeof objB) {
console.log({ objB })
}
}
There is no real magic here. You use an index variable, and let it increment:
var arr1 = [1,2,3,4,5];
var arr2 = ["a","b","c","d","e"];
let ul = document.querySelector("ul");
for (let i = 0; i < arr1.length; i++) {
let li = document.createElement('li');
for (let val of [arr1[i], arr2[i]]) {
let span = document.createElement('span');
span.textContent = val;
li.appendChild(span);
}
ul.appendChild(li);
}
<ul></ul>
There are of course other ways to loop, like with forEach, but it comes down to the same principle.
BTW, don't use string literals (template literals) for combining HTML with content, as you might have < or & characters in the content, which really should be escaped. In some cases, not escaping those may lead to unexpected side effects. By creating the elements with createElement and assigning content to their textContent or innerText properties, you avoid those potential issues. Some libraries make it possible to do this with less code, in a more functional way.
As to the initial data: in object oriented languages, like JavaScript, it is better practice to put related values together in one object. In the example, 1 and "a" apparently have a connection, so -- if possible -- you should define the initial data structure as something like this:
var data = [
{ value: 1, name: "a" },
{ value: 2, name: "b" },
{ value: 3, name: "c" },
{ value: 4, name: "d" },
{ value: 5, name: "e" }
];

Search array, find elements with ids specified another array, extract a property from the results

I have two arrays,
array1 = [{name: "a", id: 1},{name: "b", id: 2},{name: "c", id: 3}]
and
array2 = [1, 2] // --which are the ids
I want to return a new array (array3) to display ["a", "b"] and if array2 = [1,3] then array3 should be ["a", "c"]
In other words, I would like to create a new array, with the names, corresponding to its id.
You can use reduce:
let a1 = [{name:'a', id:1},{name:'b', id:2},{name:'c', id:3}]
let a2 = [1,3]
let a3 = a1.reduce((carry, current) => {
if (a2.includes(current.id)) {
carry.push(current.name)
}
return carry
}, [])
alert(a3)
User filter to select the elements that meet your criteria, and map to get the property you want.
const array1 = [{name:"a", id:1},{name:"b", id:2},{name:"c", id:3}];
const array2=[1,2];
const array3 = array1.filter(i => array2.includes(i.id)).map(i => i.name);
array3 will contain ["a", "b"]
I would go ahead and perform the below:
for(int i = 0; i<array1.length(); ++i){
for(int j = 0; j<array2.length(); ++j){
if (array1[i].id==array2[j]){
array3[j] = array[i].name;
}
}
}
Hope this is simple and it helps!

initializing in loop array with objects

I want to create such array in loop
dataset: [
{
x: 0,
y: 0,
},
{
x: 1,
y: 0.993,
}
]
But this way is not correct.
var array = new Array(10);
for (var i = 0; i < 5; ++i) {
array[i].x = 1;
array[i].y = 2;
}
How I can initialize in correct way?
The comments made by SLaks and squint are correct, so this answer is more of an explanation of why your code isn't working like you think it should, and an example of what you could do instead.
You created an array with room to hold 10 things but you didn't specify what those things were and so nothing is contained in the array.
var array = new Array(10);
you can visualize your array like this:
array = [undefined, undefined, undefined, undefined,...
The array you created was just a container for 10 things not yet defined. When you tried to assign the 'x' and 'y' properties of the array elements, you were were trying to operate on something that did not exist. To get what you want, I suggest creating an object that has the properties you want, with initial values, and then use your loop to add the number of elements you want.
var array = [];
var arrayObject = {x:0,y:0};
for(i=0; i < 10; i++){
array.push(arrayObject);
}
You can do this job in one assignment line as follows;
var dataSet = (new Array(10)).fill("initial y value").reduce((p,c,i) => p.concat({x:i,y:c}),[]);
console.log(dataSet);
I just couldn't figure what y values you would like to have so inserted the initial values of the array. Change them the way you like later. I hope it helps.
Replace the new Array(10) with
var array = Array.apply( {}, { length: 10 } ).map( function() { return {} });
new Array(10) is creating an array like
[ undefined, undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]
So you are trying to assign x on undefined
If you tried
new Array(10).map(function(){ return {}; }) it will not work either.
An es6 way to do it would be
Array.from(new Array(10), () => { return { x: 1, y: 2 }; })
In JavaScript the Array acts different than in static-typed languages, so there's no need to initialize it with fixed length.
For ECMAScript 6 specification and later:
var points = [].fill.call({ length: 5 }, {x: 1, y: 1});
It produces
[{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1},
{x: 1, y: 1}]
To ensure old browsers' support use for loop:
var points = [{x: 1, y: 1}];
for (var i = 0; i < 5; i++) points.push(points[0]);

split an array into two based on a index in javascript

I have an array with a list of objects. I want to split this array at one particular index, say 4 (this in real is a variable). I want to store the second part of the split array into another array. Might be simple, but I am unable to think of a nice way to do this.
Use slice, as such:
var ar = [1,2,3,4,5,6];
var p1 = ar.slice(0,4);
var p2 = ar.slice(4);
You can use Array#splice to chop all elements after a specified index off the end of the array and return them:
x = ["a", "b", "c", "d", "e", "f", "g"];
y = x.splice(3);
console.log(x); // ["a", "b", "c"]
console.log(y); // ["d", "e", "f", "g"]
use slice:
var bigOne = [0,1,2,3,4,5,6];
var splittedOne = bigOne.slice(3 /*your Index*/);
I would recommend to use slice() like below
ar.slice(startIndex,length);
or
ar.slice(startIndex);
var ar = ["a","b","c","d","e","f","g"];
var p1 = ar.slice(0,3);
var p2 = ar.slice(3);
console.log(p1);
console.log(p2);
const splitAt = (i, arr) => {
const clonedArray = [...arr];
return [clonedArray.splice(0, i), clonedArray];
}
const [left, right] = splitAt(1, [1,2,3,4])
console.log(left) // [1]
console.log(right) // [2,3,4]
const [left1, right1] = splitAt(-1, [1,2,3,4])
console.log(left1) // []
console.log(right1) // [1,2,3,4]
const [left2, right2] = splitAt(5, [1,2,3,4])
console.log(left1) // [1,2,3,4]
console.log(right1) // []
Some benefits compared to other solutions:
You can get the result with a one liner
When split index is underflow or overflow, the result is still correct. slice will not behave correctly.
It does not mutate the original array. Some splice based solutions did.
There is only 1 splice operation, rather than 2 slice operations. But you need to benchmark to see if there is actual performance difference.
You can also use underscore/lodash wrapper:
var ar = [1,2,3,4,5,6];
var p1 = _.first(ar, 4);
var p2 = _.rest(ar, 4);
Simple one function from lodash:
const mainArr = [1,2,3,4,5,6,7]
const [arr1, arr2] = _.chunk(mainArr, _.round(mainArr.length / 2));
const splitArrayByIndex = (arr, index) => {
if (index > 0 && index < arr.length) {
return [arr.slice(0, index), arr.slice(-1 * (arr.length - index))]
}
}
const input = ['a', 'x', 'c', 'r']
const output = splitArrayByIndex(input, 2)
console.log({ input, output })

Add two arrays without using the concat method

Here is a sample of what I would like to do
function test(r){
var arr = ['d','e','f'];
r.push(arr);
/*
More Code
*/
return r;
}
var result = test(['a','b','c']);
alert(result.length);//I want this to alert 6
What I need to do is pass in an array and attach other arrays to the end of it and then return the array. Because of passing by reference I cannot use array.concat(array2);. Is there a way to do this without using something like a for loop to add the elements one by one. I tried something like r.push(arr.join()); but that did not work either. Also, I would like the option of having objects in the arrays so really the r.push(arr.join()); doesn't work very well.
>>> var x = [1, 2, 3], y = [4, 5, 6];
>>> x.push.apply(x, y) // or Array.prototype.push.apply(x, y)
>>> x
[1, 2, 3, 4, 5, 6]
Alternatively using destructuring you can now do this
//generate a new array
a=[...x,...y];
//or modify one of the original arrays
x.push(...y);
function test(r){
var _r = r.slice(0), // copy to new array reference
arr = ['d','e','f'];
_r = _r.concat(arr); // can use concat now
return _r;
}
var result = test(['a','b','c']);
alert(result.length); // 6
This is emulbreh's answer, I'm just posting the test I did to verify it.
All credit should go to emulbreh
// original array
var r = ['a','b','c'];
function test(r){
var arr = ['d','e','f'];
r.push.apply(r, arr);
/*
More Code
*/
return r;
}
var result = test( r );
console.log( r ); // ["a", "b", "c", "d", "e", "f"]
console.log( result === r ); // the returned array IS the original array but modified

Categories

Resources