Create array of objects using arrays of values - javascript

I have fairly lot of data in this form
A B C D
-------
1 2 3 4
5 6 7 8
9 1 2 3
represented using javascript types as :
df = {A: [1,5,9], B: [2,6,1], C: [3,7,2], D:[4,8,3]}
I want to convert this into this form:
[{A:1, B:2, C:3, D:4}, {A:5, B:6, C:7, D:8}, {A:9, B:1, C:2, D:3}]
I tried implementing it as:
keyes = ["A", "B", "C", "D"]
getrow = (i) => Object.assign( ...keyes.map((k) => ({[k]: df[k][i]})))
df.A.map( (x,j) => getrow(j))
But this is slow for the size of the table I have. Is there any faster way to do this?

You could use reduce and forEach loops to create array of objects.
const df = {
A: [1, 5, 9],
B: [2, 6, 1],
C: [3, 7, 2],
D: [4, 8, 3]
}
const result = Object.keys(df).reduce((r, k) => {
df[k].forEach((e, i) => {
if (!r[i]) r[i] = {}
r[i][k] = e;
})
return r;
}, [])
console.log(result)
Or maybe for better performance you can go with the for loops.
const df = {
A: [1, 5, 9],
B: [2, 6, 1],
C: [3, 7, 2],
D: [4, 8, 3]
}
const result = [];
for (let key in df) {
for (let i = 0; i < df[key].length; i++) {
if (!result[i]) result[i] = {}
result[i][key] = df[key][i]
}
}
console.log(result)

You could take two for loops, and check the existence of the object at a certain index. Then assign the value to the property.
This version is faster than the use of array methods.
var data = { A: [1, 5, 9], B: [2, 6, 1], C: [3, 7, 2], D: [4, 8, 3] },
result = [],
key, values,
i;
for ([key, values] of Object.entries(data)) {
for (i = 0; i < values.length; i++) {
if (!result[i]) result[i] = {};
result[i][key] = values[i];
}
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to concat arrays alternatively every 2 items? JS

I have:
array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
array2 = ['a', 'b', 'c'];
I got the concat of arrays working, but only one at a time:
var alternatingArrayResult = [array1, array2].reduce(function (r, a) {
return a.forEach(function (a, i) {
return (r[i] = r[i] || []).push(a);
}), r;
}, []).reduce(function (a, b) {
return a.concat(b);
});
// => alternatingArrayResult = [1, 'a', 2, 'b', 3, 'c', 4, 5, 6, 7, 8, 9];
I want to add two items from array 1, then one from array 2 - and so on.
Desired output:
result = [1, 2, 'a', 3, 4, 'b', 5, 6, 'c', 7, 8, 9];
var array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array2 = ['a', 'b', 'c'];
var alternatingResultArray = [array1, array2].reduce(function (r, a) {
return a.forEach(function (a, i) {
return (r[i] = r[i] || []).push(a);
}), r;
}, []).reduce(function (a, b) {
return a.concat(b);
});
console.log(alternatingResultArray);
You could get a lenght and iterate the parts for pushing.
const
array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9],
array2 = ['a', 'b', 'c'],
result = [];
for (i = 0, l = Math.max(Math.ceil(array1.length / 2), array2.length); i < l; i++) {
result.push(
...array1.slice(i * 2, (i + 1) * 2),
...array2.slice(i, i + 1),
);
}
console.log(...result);
A more abstact version with size of the wanted subarrays.
const
array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9],
array2 = ['a', 'b', 'c'],
data = [array1, array2],
sizes = [2, 1]
result = [];
for (i = 0, l = Math.max(...data.map(({ length }, i) => Math.ceil(length / sizes[i]))); i < l; i++) {
data.forEach((a, j) => result.push(...a.slice(i * sizes[j], (i + 1) * sizes[j])));
}
console.log(...result);
Use Array.map with a thisArg for the desired result (see MDN).
thisArg (Optional) Value to use as this when executing callback.
let array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let array2 = ['a', 'b', 'c'];
let arrayConcatted = array1
.flatMap( function(v, i) {
// ^ not arrow to keep thisArg in scope
const arr2Value = i && i % 2 === 0 && this.length && this.shift();
return arr2Value ? [arr2Value, v] : v;
}, array2.slice())
// ^ 'this', a copy of array2
console.log(JSON.stringify(arrayConcatted));
// IE
var arrConcatIE = [];
var arr2Clone = array2.slice();
for (var i=0; i < array1.length; i +=1) {
const arr2Value = i && i % 2 === 0 && arr2Clone.length && arr2Clone.shift();
if (arr2Value) {
arrConcatIE.push(arr2Value);
}
arrConcatIE.push(array1[i]);
}
console.log(JSON.stringify(arrConcatIE));

Convert object with multiple arrays to array of objects

I stuggle a lot with data I get from an API:
This is the way the data gets returned, the amout of arrays differs.
const objData = {
arr1: [1,2,3],
arr2: [1,2,1],
arr3: [2,1,2],
arr4: ["a","b", "c"]
}
This is the way it SHOULD look
const desired = [
{a: 1, b: 1, c: 2, d: "a"},
{a: 2, b: 2, c: 1, d: "b"},
{a: 2, b: 1, c: 2, d: "c"}
]
This gives me the desired result, but it is not dymanic, since I have to provide the names of the arrays, and the amount of arrays in the object is not allowed to change.
const DataObj = []
for (let i = 0; i < objData.arr1.length; i++) {
const objX = {
a: objData.arr1[i],
b: objData.arr2[i],
c: objData.arr3[i],
d: objData.arr4[i],
}
DataObj.push(objX)
}
Can anybody help me to solve this? How can I make this independent from the names of the arrays and the amount of arrays in the dataset?
You could map the arrays with new objects.
const
objData = { arr1: [1, 2, 3], arr2: [1, 2, 3], arr3: [2, 1, 2], arr4: ["a", "b", "c"] },
keys = { arr1: 'a', arr2: 'b', arr3: 'c', arr4: 'd' },
result = Object
.entries(objData)
.reduce((r, [key, array]) => array.map((v, i) => ({ ...r[i], [keys[key]]: v })), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Non functional approach, use integers to get your letters
const objData = {
arr1: [1, 2, 3, 5],
arr2: [1, 2, 1, 4],
arr3: [2, 1, 2, 3],
arr4: ["a", "b", "c", "d"]
}
const len = Object.values(objData)[0].length;
let cnt = 97;
let newObj = {};
const list = [];
for (let i = 0; i < len; i++) {
for (let key in objData) {
newObj[String.fromCharCode(cnt)] = objData[key][i];
++cnt
}
list.push(newObj);
cnt = 97;
newObj = {};
}
console.log(list)

Convert Dictionary having array value for keys into a list in Javascript

I have a dictionary structure as follows :
data = { a : [5, 10], b : [1, 12] , c : [6, 7]}
I need to convert this to follows :
[ a, 5, 10 ], [ b, 1, 12 ], [ c, 6, 7 ]
I've already tried using Object.entries(data), but it returned the data like : [a, [5, 10]], [b, [1, 12]]
How can i do this using JavaScript?
You could map the key/values in a new array.
var data = { a : [5, 10], b : [1, 12] , c : [6, 7]},
result = Object.entries(data).map(([k, v]) => [k, ...v]);
console.log(result);
Another way:
const data = { a : [5, 10], b : [1, 12] , c : [6, 7]};
const result = Object.entries(data).map(pair => pair.flat());
console.log(result);
So with Object.keys() and reduce() you can solve as the following:
const data = { a: [5, 10], b: [1, 12], c: [6, 7] };
const result = Object.keys(data).map(e => {
return data[e].reduce((a, c) => {
a.push(c);
return a;
}, Array.from(e));
});
console.log(result);
I hope that helps!
var dict = { 'a': 'aa', 'b': 'bb' };
var arr = [];
for (var key in dict) {
if (dict.hasOwnProperty(key)) {
arr.push( [ key, dict[key] ] );
}
}
this might helps you out

return array from comparing to arrays _ lodash

let a = [{
a:1,
b:3,
c:[1, 2, 6]
},
{
a:3,
b:10,
c:[2, 5, 4]
},
{
a:4,
b:3,
c:[7, 12, 6]
},
{
a:4,
b:12,
}]
let b = [2, 6]
I want to return an array from a object that matches from b arrays.
I used :
lodash.forEach(b , (value)=>{
lodash.filter(a, {c: value})
}
but this doesnt work . I tried to simple my code for better underestanding.
You could filter the array by looking if the values of b are included in c.
var a = [{ a: 1, b: 3, c: [1, 2, 6] }, { a: 3, b: 10, c: [2, 5, 4] }, { a: 4, b: 3, c: [7, 12, 6] }, { a: 4, b: 12 }],
b = [2, 6],
result = a.filter(({ c = [] }) => b.some(v => c.includes(v)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
For getting only items who match completely, you could use Array#every instead of Array#some.
var a = [{ a: 1, b: 3, c: [1, 2, 6] }, { a: 3, b: 10, c: [2, 5, 4] }, { a: 4, b: 3, c: [7, 12, 6] }, { a: 4, b: 12 }],
b = [2, 6],
result = a.filter(({ c = [] }) => b.every(v => c.includes(v)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
To find objects with c contain all b values you can use Array.filter() and Array.every():
let a = [{ a: 1, b: 3, c: [1, 2, 6] }, { a: 3, b: 10, c: [2, 5, 4] }, { a: 4, b: 3, c: [7, 12, 6] }, { a: 4, b: 12 }];
let b = [2, 6]
console.log(a.filter(({c = []}) => b.every(v => c.includes(v))));
if you want common values use Array.some() instead of Array.every():
let a = [{ a: 1, b: 3, c: [1, 2, 6] }, { a: 3, b: 10, c: [2, 5, 4] }, { a: 4, b: 3, c: [7, 12, 6] }, { a: 4, b: 12 }];
let b = [2, 6]
console.log(a.filter(({c = []}) => b.some(v => c.includes(v))));
I believe this is what you want - you can do it in pure JS:
let a = [{
a:1,
b:3,
c:[1, 2, 6]
},
{
a:3,
b:10,
c:[2, 5, 4]
},
{
a:4,
b:3,
c:[7, 12, 6]
},
{
a:4,
b:12,
}]
let b = [2, 6]
let c = a.filter(({ c = [] }) => c ? b.some(n => c.includes(n))) : false;
console.log(c);
Assuming you want to filter objects in array a that have atleast one value in c which exists in b array.
You can use Array.filter, Array.some & Array.includes
let a=[{a:1,b:3,c:[1,2,6]},{a:3,b:10,c:[2,5,4]},{a:4,b:3,c:[7,12,6]},{a:4,b:12,}];
let b=[2,6];
let result = a.filter(v => v.c && v.c.some(v1 => b.includes(v1)));
console.log(result);
You can use lodash as follows
let a=[{a:1,b:3,c:[1,2,6]},{a:3,b:10,c:[2,5,4]},{a:4,b:3,c:[7,12,6]},{a:4,b:12,}];
let b=[2,6];
let result = _.filter(a, v => v.c && _.some(v.c, c => _.includes(b,c)));
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

javascript pattern matching object

Given a javascript object array eg.
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]
is there a faster way of getting all the b values from each object which meet a specific criteria such as a = 1 to return something like
b_consolidated = [2,3]
instead of looping through every object in the array?
You can use Array#filter function to get the items of your criteria, then use Array#map to get only b property.
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];
let values = objArray.filter(item => item.a === 1).map(item => item.b);
console.log(values);
Or you can do this in one loop
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];
let values = [];
objArray.forEach(item => {
if(item.a === 1) {
values.push(item.b);
}
});
console.log(values);
You could use Array#reduce in a single loop.
let array = [{ a: 1, b: 2, c: 3}, { a: 1, b: 3, c: 2 }, { a: 2, b: 5, c: 1 }],
result = array.reduce((r, o) => o.a === 1 ? r.concat(o.b) : r, []);
console.log(result);
Fastest version with for loop.
let array = [{ a: 1, b: 2, c: 3}, { a: 1, b: 3, c: 2 }, { a: 2, b: 5, c: 1 }],
i, l,
result = [];
for (i = 0, l = array.length; i < l; i++) {
if (array[i].a === 1) {
result.push(array[i].b);
}
}
console.log(result);
You only need to iterate over the array once, if you use reduce:
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]
let result = objArray.reduce((arr, val) => {
if(val.a === 1)
arr.push(val.b);
return arr;
}, []);
console.log(result);
This is as fast as it'll get, short of a manual for loop:
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]
let result = [];
for(var i = 0 ; i < objArray.length; i++){
if(objArray[i].a === 1)
result.push(objArray[i].b);
}
console.log(result);
Here's a JSPerf to illustrate the difference.
A manual for loop is by far the fastest.
More faster would be using .reduce
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}];
objArray.reduce(function(res,obj){
if(obj.a===1)
res.push(obj.b);
return res;
},[]);
// [2,3]
In Ramda
let objArray = [{a: 1, b: 2 , c:3},{a: 1, b:3, c:2},{a: 2, b:5, c:1}]
R.pipe(
R.filter(R.propEq('a', 1)),
R.pluck('b')
)(objArray)
// [2, 3]
Filter returns the array values matched by the condition.
Pluck returns a new list by plucking the same named property off all objects in the list supplied.
Edit 1:
Example of using the mentioned reduce pattern in Ramda:
R.reduce((acc, x) => R.ifElse(
R.propEq('a', 1),
(item) => R.pipe(R.prop('b'), R.append(R.__, acc))(item),
R.always(acc)
)(x), [])(objArray)
// [2, 3]

Categories