I have two arrays:
arr1 = [name, speed, power, energy];
arr2 = [
[Ed, 10, 20, 30],
[Robert, 15, 25, 35],
[Paul, 8, 18, 28]
];
How can I combine the two array's to an array of objects, using the first array for keys and the second one for values?
arr3 = [
{
name: "Ed",
speed:"10",
power:"20",
energy:"30"
},
{
name: "Robert",
speed:"15",
power:"25",
energy:"35"
},
{
name: "Paul,
speed:"8",
power:"18",
energy:"28"
}
];
You can simply create an array of objects using map
arr2.map(row => {
const name = item[0];
const speed = item[1];
const power = item[2];
const energy = item[3];
return { name, speed, power, energy }
})
Running this on your given arr2 gives the following result
var arr2 = [['Ed', 10, 20, 30],['Robert', 15, 25, 35],['Paul', 8, 18, 28]];
var arr3 = arr2.map(row => {
const name = item[0];
const speed = item[1];
const power = item[2];
const energy = item[3];
return { name, speed, power, energy }
});
console.log(arr3)
// arr3 = [
// {name: "Ed", speed:10, power:20, energy:30},
// {name: "Robert", speed:15, power:25, energy:35},
// {name: "Paul", speed:8, power:18, energy:28}
// ]
Firstly, I am assuming the tokens name, speed, power, energy are actually strings and you forgot to include the quotes.
The Object.fromEntries method takes an array of tuples (two-item arrays) and converts it into an object.
If we zip the keys from arr1 with the values from each array in arr2, we can acheive the desired mapping.
arr1 = ["name", "speed", "power", "energy"];
arr2 = [["Ed", 10, 20, 30],["Robert", 15, 25, 35],["Paul", 8, 18, 28]];
arr3 = arr2.map(objArr =>
Object.fromEntries(arr1.map((key, i) =>
[key, objArr[i]] // key-value tuple
))
)
console.log(arr3);
Ruby has this really useful method called zip, so you want basically that for each of arr2 but in JavaScript. In other words, zip arr1 keys with each person's properties.
Below is a snippet that implements a basic zip function and then uses it to create the object in the format you're looking for:
arr1 = ["name", "speed", "power", "energy"];
arr2 = [
["Ed", 10, 20, 30],
["Robert", 15, 25, 35],
["Paul", 8, 18, 28],
];
Array.prototype.zip = function(a) {
return this.map((k, i) => [k, a[i]]);
};
arr3 = arr2.map(p => Object.fromEntries(arr1.zip(p)));
console.log(arr3);
Related
I have two arrays like this
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
I need to map the elements of arr1 to each nested element at the same index of arr2 so that I get result in an array with two objects like this
result = [ { "name" : "John", "age" : 31, "spouseName": "Jill", "kids" : 3 },
{ "name" : "Jack", "age" : 44, "spouseName": "Emily", "kids" : 2 }]
I have tried using nested forEach to loop over each of element in arr2 but it only spits out the items in index 1 and not at index 0 as it get overwritten in the loop
arr2.forEach((element, index) => {
element.forEach((el) => {
result[arr1[index]] = el
})
});
I know I am missing something but can't figure out
You can loop through the arrays as follows:
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
result = arr2[0].map((_, i) => arr1.reduce((acc, k, j) => {
acc[k] = arr2[j][i];
return acc;
}, {}));
console.log(result);
You can loop through the names in array 2 and assuming the following arrays have the correct number of elements in you can use the index of that name to get the corresponding items from the other arrays:
const arr1 = [];
const arr2 = [["John", "Jack"], [31, 44], ["Jill", "Emily"], [3, 2]];
arr2[0].forEach((item, index) => {
arr1.push({
"name": item,
"age": arr2[1][index],
"spouseName": arr2[2][index],
"kids": arr2[3][index],
});
})
console.log(arr1);
If you need to use arr1 as your property names and you don't know the number of items in arr1, I would do it like this:
const arr1 = ["name", "age", "spouseName", "kids"];
const arr2 = [
["John", "Jack", "1", "2", "3"],
[31, 44, 22, 41, 42],
["Jill", "Emily", "1", "2", "3"],
[3, 2, 1, 5, 2]
];
const result = arr2[0].map((name, index) => {
let returnValue = {};
returnValue[arr1[0]] = name;
for (let i = 1; i < arr1.length; i++) {
returnValue[arr1[i]] = arr2[i][index];
}
return returnValue;
});
console.log(result)
It is a slightly more efficient way than using reduce in your map loop: https://jsbench.me/zpl6lvmb6r/1
I have a single dimensional and an array of Objects
array1 = [1, 3, 15, 16, 18];
array2 = [
{ id: 1, dinner : pizza },
{ id: 15, dinner : sushi },
{ id: 18, dinner : hummus }
]
I'm trying to remove values from array1 that are not in array2 based on the id.
I know how to remove in two single dimensional arrays but I'm unable to modify the code to remove when array2 is an array of Objects.
const array1 = array1.filter(id => array2.includes(id));
Any help would be appreciated.
Both arrays are single dimension arrays.
use .some() function along with .filter() function to remove those numbers from array1 which are not present as id in any of the objects in array2
const array1 = [1, 3, 15, 16, 18];
const array2 = [
{ id: 1, dinner : 'pizza' },
{ id: 15, dinner : 'sushi' },
{ id: 18, dinner : 'hummus' }
]
const filteredArr = array1.filter(v => array2.some(o => v == o.id));
console.log(filteredArr);
You can map all Ids and then filter
var array1 = [1, 3, 15, 16, 18];
var array2 = [
{ id: 1, dinner : "pizza" },
{ id: 15, dinner : "sushi" },
{ id: 18, dinner : "hummus" }
]
const Ids = array2.map(i=> i.id);
var res = array2.filter(i => Ids.includes(i.id));
var res2 = Ids.filter(i => array1.includes(i))// Or, just to get common Ids
console.log(res)
console.log(res2)
But I suggest you should use reduce to avoid two passes:
var array1 = [1, 3, 15, 16, 18];
var array2 = [
{ id: 1, dinner : "pizza" },
{ id: 15, dinner : "sushi" },
{ id: 18, dinner : "hummus" }
]
var res = array2.reduce((acc, {id})=>{
if(array1.includes(id)){
acc = [...acc, id]
}
return acc
},[]);
console.log(res)
I want to filter the objects from array:
let x = [{a: 100, categories: [22, 23 ]
}, {a: 101, categories: [20, 21 ] }];
let y = [22]; //can be multiple
let result = x.filter(i => y.includes(i.categories) );
console.log(result);
// result = []
Expected Output:
[{a: 100, categories: [22, 23 ]}]
but I get empty array.
Use some to see if some of the items are in the categories array.
let x = [{a: 100, categories: [22, 23 ] }, {a: 101, categories: [20, 21 ] }];
let y = [22]; //can be multiple
let result = x.filter(i => y.some(a => i.categories.includes(a)));
console.log(result);
You're checking whether the entire array i.categories is in y, use Array.prototype.some to check if any element of i.categories is in y:
let x = [{a: 100, categories: [22, 23 ] }, {a: 101, categories: [20, 21 ] }];
let y = [22]; //can be multiple
let result = x.filter(i => y.some(x => i.categories.includes(x)));
console.log(result);
If x, .categories, or y is significantly large, you can achieve a significant speed improvement by first converting y to a Set. Set.prototype.has provides much faster lookup times, O(1), compared to Array.prototype.includes, O(n) -
const x =
[ { a: 100, categories: [ 22, 23 ] }
, { a: 101, categories: [ 20, 21 ] }
, { a: 102 }
]
const y =
[ 22 ] //can be multiple
const ySet =
new Set(y) // has O(1) lookup
let result =
x.filter(({ categories = [] }) =>
categories.some(c => ySet.has(c)) // <-- use set lookup
)
console.log(result)
// [ { a: 100, categories: [ 22, 23 ] } ]
The problem I have is, that I want to combine a 2D Array like this:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 32, 12, … ],
[ "Mercedes", 24, 21, … ],
[ "Toro Rosso", 7, 8, … ]
]
So in this example I have the String "Mercedes" twice at index 0 in the arrays.
What I want the output to be is the following:
[
[ "Renault", 61, 16, … ],
[ "Ferrari", 58, 10, … ],
[ "Mercedes", 56, 33, … ],
[ "Toro Rosso", 7, 8, … ]
]
So if a String like "Mercedes" is appearing twice in that array I want the second one to be deleted. But the values from the second array must be taken over into the first "Mercedes" Array.
It seems that you actually want to aggregate similar values in the array. Therefore you could do a cycle in foreach and save yourself in a temporary array the string values already known and instead in another your merged classes. At that point, as you scroll through your array, you can check if you have already added an equal string in the first fake, and if so, you can take its index and aggregate them correctly in the other array.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
var tmp1 = [], tmp2 = [];
arr.forEach(function(currentValue, index, arr) {
// currentValue contain your element
// index contain the index of your element
// arr contain you entire "values" array
var ind = tmp1.indexOf(currentValue[0]);
if(ind === -1) {
tmp1.push(currentValue[0]);
tmp2.push(currentValue);
} else {
tmp2[ind][1] += currentValue[1];
tmp2[ind][2] += currentValue[2];
}
});
console.log(tmp2);
You can use reduce() to build a object and then use Object.values()
const arr = [
[ "Renault", 61, 16 ],
[ "Ferrari", 58, 10],
[ "Mercedes", 32, 12],
[ "Mercedes", 24, 21],
[ "Toro Rosso", 7, 8]
]
let res = arr.reduce((ac, [k, ...rest]) => {
if(!ac[k]) ac[k] = [];
ac[k] = ac[k].concat(k,...rest);
return ac;
},[])
console.log(Object.values(res))
Sure, by creating an array for your names and then separate the unique ones from them, at last, match them with the index.
let arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
]
let c = [...new Set(arr.map(a => a[0]))] // get unique values of all arr[0]
let ans = arr.filter((a, post) => {
if (c[post]) { // check if index exists because we seperated one, the last is undefined here
if (a[0] == c[post]) {
return a;
}
} else {
return a; // else return as usual
}
})
console.log(ans)
You get the filtered array.
You can iterate over the array and keep a map object of the names you already processed with their index in the result array so you can access them quicker when you need to push more values.
i.e:
{
"Renault": 0,
"Ferrari": 1,
"Mercedes": 2,
"ToroRosso": 3
}
Here is a running example with the steps:
const arr = [
["Renault", 61, 16],
["Ferrari", 58, 10],
["Mercedes", 32, 12],
["Mercedes", 24, 21],
["Toro Rosso", 7, 8]
];
let map = {};
let globalIndex = 0;
let resultArray = [];
arr.forEach((currentArray) => {
const [name, ...rest] = currentArray;
if (map[name] === undefined) {
// if our map doesn't already store this value
// then store it with it's current index
map[name] = globalIndex;
// push it to the result array
resultArray[globalIndex] = currentArray;
// increment the global index
//so we can keep track of it in the next iteration
globalIndex++;
} else {
// we already have an array with this name
// grab the relevant index we previously stored
// and push the items without the name via this index
const relevantIdx = map[name];
resultArray[relevantIdx] = [
...resultArray[relevantIdx],
...rest
]
}
})
console.log(resultArray);
var foo = { "a": [1,2,3] }
var bar = { "b": [7,8,9] }
output should look like this
[ {a: 1, b: 7}, {a: 2, b: 8}, {a:3, b: 9}]
How can I do this using ramda or javascript functional programming ?
I have done this using for loop i = 0, is it possible using functional ramda programming
If both arrays are always the same length, you can do this using map.
function mergeArrays(arr1, arr2) {
return arr1.map(function(item, index) {
return {
a: arr1[index], //or simply, item
b: arr2[index]
};
});
}
var a = [1, 2, 3];
var b = [7, 8, 9];
var joined = mergeArrays(a, b);
document.getElementById('result').innerHTML = JSON.stringify(joined, null, 2);
<pre id="result">
</pre>
You can achieve this using R.transpose to convert an array of [[1,2,3], [7,8,9]] to [[1, 7], [2, 8], [3, 9]] and then map over it with R.zipObj.
const fn = R.compose(
R.map(R.zipObj(["a", "b"])),
R.transpose
)
const a = [1, 2, 3], b = [7, 8, 9]
const result = fn([a, b])
console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
If you would prefer to pass a and b as two arguments to fn rather than an array then you can swap R.transpose in the example above with R.unapply(R.transpose).
Assuming you want [{a:1,b:7},{a:2,b:8},{a:3,b:9}] it can be done pretty easily with map using the index to get the value in b:
var result = a.map((v, i) =>({ a: v, b: b[i] }));
i am having an array
const peopleObject = { "123": { id: 123, name: "dave", age: 23 },
"456": { id: 456, name: "chris", age: 23 }, "789": { id: 789, name:
"bob", age: 23 }, "101": { id: 101, name: "tom", age: 23 }, "102":
{ id: 102, name: "tim", age: 23 } }
for this particular i have created a code that convrts array to object i hope this is usefull for you
const arrayToObject = (array) =>
array.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
const peopleObject = arrayToObject(peopleArray)
console.log(peopleObject[idToSelect])
Your expected output doesn't have a valid format. You should store the data in array. Like ,
var output = [];
var a = [1,2,3], b = [7,8,9];
for(var i=0; i< a.length; i++){
var temp = {};
temp['a'] = a[i];
temp['b'] = b[i];
output.push(temp);
}
You cannot store the result in an object the way you want. Objects are key-value pairs. But what you expect is only the values without keys which is not possible!
create function form ramda's addIndex and map
const data = { keys: ['a', 'b', 'c'], values: ['11', '22', '33'] }
const mapIndexed = R.addIndex(R.map)
const result = mapIndexed((item, i) => {
return { [item]: data.values[i] }
}, data.keys)
You will get an array of objects