so I have a data structure that looks like this :
data = {
a: [1, 2, 3, 4, 5],
b: ["a", "b", "c", "d", "e"],
c: ["123", "235423", "12312", "1231", "12312"],
d: ["aa", "bb", "cc", "dd", "ee"],
...
}
and I need to convert it into a following structure:
[
{ a: 1, b: "a", c: "123", d: "aa", ... },
{ a: 2, b: "b", c: "235423", d: "bb", ... },
{ a: 3, b: "c", c: "12312", d: "cc", ... },
{ a: 4, b: "d", c: "1231", d: "dd", ... },
{ a: 5, b: "a", c: "12312", d: "ee", ... },
]
the number of keys in data can vary, but the length of the values will always be same across all arrays, i.e. data[a].length === data[z].length will always be true.
My solution:
const doStuff = () => {
const result = [];
const keys = Object.keys(data);
if (!keys) return result;
const valuesLength = keys[0].length
const result = [];
for (let i = 0; i < valuesLength ; i++) {
const obj = {};
for (const key in data) {
obj[key] = data[key][i];
}
result.push(obj);
}
return result;
};
is using two for loops is not most effective one since the number of keys can be large, so i'm looking for a most optimal solution
You may traverse your source object keys (Object.keys()) with Array.prototype.reduce(), looping inner arrays with Array.prototype.forEach() and assigning corresponding property of resulting object:
const src = {a:[1,2,3,4,5],b:["a","b","c","d","e"],c:["123","235423","12312","1231","12312"],d:["aa","bb","cc","dd","ee"]},
result = Object
.keys(src)
.reduce((acc, key, i, keys) => {
src[key].forEach((v, j) => {
acc[j] = acc[j] || {}
acc[j][key] = v
})
return acc
}, [])
console.log(result)
.as-console-wrapper{min-height:100%;}
The solution is going to require two loops. One to go over the properties in the object, the other to loop over the array of values.
Personally I would use reduce and forEach for the two loops
const data = {
a: [1, 2, 3, 4, 5],
b: ["a", "b", "c", "d", "e"],
c: ["123", "235423", "12312", "1231", "12312"],
d: ["aa", "bb", "cc", "dd", "ee"]
}
const result = Object.entries(data).reduce((arr, [key, values]) => (
values.forEach((value, index) => {
arr[index] = {
...arr[index],
[key]: value
};
}),
arr), []);
console.log(result);
without the fat arrows and destructuring
var data = {
a: [1, 2, 3, 4, 5],
b: ["a", "b", "c", "d", "e"],
c: ["123", "235423", "12312", "1231", "12312"],
d: ["aa", "bb", "cc", "dd", "ee"]
};
var result = Object.entries(data).reduce(function(result, entry) {
var key = entry[0];
var arr = entry[1];
arr.forEach(function(value, index) {
result[index] = result[index] || {};
result[index][key] = value;
});
return result;
}, []);
console.log(result);
Please check the below code:
var data = {
a: [1, 2, 3, 4, 5],
b: ["a", "b", "c", "d", "e"],
c: ["123", "235423", "12312", "1231", "12312"],
d: ["aa", "bb", "cc", "dd", "ee"]
}
var anotherObjArray = [];
for(var i=0;i<data[Object.keys(data)[0]].length;i++){
let tempObj = {};
for(var j=0;j<Object.keys(data).length;j++){
tempObj[Object.keys(data)[j]] = data[Object.keys(data)[j]][i];
}
anotherObjArray.push(tempObj);
}
anotherObjArray is the final array for your requirement.
By assuming same length arrays, you could get the entries and reduce the array by mapping all values along with the object at the same index and the new property.
const
data = { a: [1, 2, 3, 4, 5], b: ["a", "b", "c", "d", "e"], c: ["123", "235423", "12312", "1231", "12312"], d: ["aa", "bb", "cc", "dd", "ee"] },
result = Object
.entries(data)
.reduce((r, [k, a]) => a.map((v, i) => ({ ...r[i], [k]: v })), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
From this object:
{"a": "a", "b": "b", "c": [1,2,3]}
I would like to get this:
{"a": "a", "b": "b", "c":1}
{"a": "a", "b": "b", "c":2}
{"a": "a", "b": "b", "c":3}
how can I do?
You can map the data.c, and get the a, b from the origin object and c from the map callback item parameter.
const data = {"a": "a", "b": "b", "c": [1,2,3]}
const result = data.c.map(i => ({
a: data.a,
b: data.b,
c: i,
}))
console.log(result)
Map over object[c] and return the object a copy of the object itself + the current value:
let expand = (obj, key) => obj[key].map(val => ({...obj, [key]: val}))
test = {"a": "a", "b": "b", "c": [1,2,3]}
result = expand(test, 'c')
console.log(result)
First, you should check if that the obj[key] is an array. If it is, continue with mapping, else just return the object
const transform = (obj, key) => {
if (!Array.isArray(obj[key])) return obj
return obj[key].map(val => ({ ...obj, [key]: val }))
}
console.log(transform({ a: "a", b: "b", c: "c" }, "c"))
console.log(transform({ a: "a", b: "b", c: [1, 2, 3] }, "c"))
console.log(transform({ a: "a", b: "b", d: [4, 5, 6] }, "d"))
I want to get the largest object in an array of objects, the code I'm using works fine, but I wonder if there is a better way of doing the same. This is the code I'm using.
data=[
{group: "a", A: 65, N: 20},
{group: "b", R: 52},
{group: "c", N: 20, A: 2, R: 2},
{group: "d", R: 15, N: 12},
]
len = []
for (var i in data){
len.push(Object.keys(data[i]).length)
}
for (var i in data){
if (Object.keys(data[i]).length==Math.max.apply(null, len)){
subgroups = Object.keys(data[i]).slice(1).sort();
}
}
console.log(subgroups);
I think one loop is sufficient to do this.
var data=[
{group: "a", A: 65, N: 20},
{group: "b", R: 52},
{group: "c", N: 20, A: 2, R: 2},
{group: "d", R: 15, N: 12},
],
max = Object.keys(data[0]).length,
largestObj = data[0];
data.forEach(i=>{
if(Object.keys(i).length> max){
max = Object.keys(i).length;
largestObj = i;
}
});
console.log(max);
console.log(largestObj);
An example using Array.prototype.reduce
const [biggestObject] = data.reduce(
([acc, length], entry) => {
const len = Object.keys(entry).length;
return length > len ? [acc, length] : [entry, len];
},
[{}, 0]
);
To sort the whole array seems stupid, one loop is enough using reduce function
const { element } = data.reduce((agg, element) => {
const length = Object.keys(v).length
if (length > agg.length) {
return { element, length }
}
return agg
}, { element: null, length: 0 })
You can just sort the array using the criteria you used for filling the len array.
data.sort((x, y) => {
return Object.keys(y).length - Object.keys(x).length
});
Result:
0: {group: "c", N: 20, A: 2, R: 2}
1: {group: "a", A: 65, N: 20}
2: {group: "d", R: 15, N: 12}
3: {group: "b", R: 52}
In Javascript, is there a way to filter the JSON file based on the values in the array?
For example, with the following array:
["c", "f"]
and the JSON object file:
[{
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
"f": 6
},{
"a": 2,
"b": 4,
"c": 6,
"d": 8,
"e": 10,
"f": 12
}]
I would like to generate the following result:
[{
"c": 3,
"f": 6
},{
"c": 6,
"f": 12
}]
You could map the values of the given keys for a new object.
var keys = ["c", "f"],
data = [{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }, { a: 2, b: 4, c: 6, d: 8, e: 10, f: 12 }],
filtered = data.map(o => Object.assign(...keys.map(k => ({ [k]: o[k] }))));
console.log(filtered);
You can use map() and reduce() for this.
var keys = ["c", "f"];
var arr = [{"a":1,"b":2,"c":3,"d":4,"e":5,"f":6},{"a":2,"b":4,"c":6,"d":8,"e":10,"f":12}];
var result = arr.map(o => {
return keys.reduce((r, k) => (o[k] && (r[k] = o[k]), r), {})
})
console.log(result)
Previously I asked this question, (how to filter data in array loop) but I have some changes in my second array,.. as given below..
In my array is like this,
var myColumnDefs = [
{a: "hh", b: "hh", c: "jk", d: "ggh", e: "hvh"},
{a: "dd", b: "gg", d: "nn", e: "rr", f: "jj"},.....
]
I want to filter data and insert data in new array like this
var newarray = {a,b,c,d,e,f}
& another array
var mysecondarray = [
{hh,hhjk,ggh,hvh,null},
{dd,gg,null,nm,rr,jj},....
]
First collect every key, then collect the data.
var myColumnDefs = [{ a: "hh", c: "jk", d: "ggh", e: "hvh" }, { a: "dd", b: "gg", d: "nn", e: "rr", f: "jj" }],
result = function (array) {
var r = { keys: [], data: [] }, o = {};
array.forEach(function (a) {
Object.keys(a).forEach(function (k) {
if (!(k in o)) {
o[k] = r.keys.push(k) - 1;
}
});
});
r.keys.sort(); // sort all keys
array.forEach(function (a) {
r.data.push(r.keys.map(function (k) {
return a[k];
}));
});
return r;
}(myColumnDefs);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
I have the following:
var object = {
a: ["A1"],
b: ["B1", "B2"],
c: ["C1", "C2", "C3", "C4"]
};
And I want to convert the above to this:
var result = {
A1: "a",
B1: "b",
B2: "b",
C1: "c",
C2: "c",
C3: "c",
C4: "c"
};
I am new to Javascript. Is there any effective way to do this? I can import other libraries if needed and assume the values in the array is unique. Thanks.
Try this,
var object = {
a: ["A1"],
b: ["B1", "B2"],
c: ["C1", "C2", "C3", "C4"]
};
var keys = Object.keys(object);
var obj = {};
for(var j=0,l=keys.length;j<l;j++){
for (var i = 0; i < object[keys[j]].length; i++) {
obj[object[keys[j]][i]] = keys[j];
}
}
console.log(obj);
var object = {
a: ["A1"],
b: ["B1", "B2"],
c: ["C1", "C2", "C3", "C4"]
};
var keys = Object.keys(object);
var obj = {};
for(var j=0,l=keys.length;j<l;j++){
for (var i = 0; i < object[keys[j]].length; i++) {
obj[object[keys[j]][i]] = keys[j];
}
}
console.log(obj);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Solution with forEach and arrow function (ES6 standard)
var object = { a: ["A1"], b: ["B1", "B2"], c: ["C1", "C2", "C3", "C4"] };
var result = {};
Object.keys(object).forEach(k =>
object[k].forEach(a => result[a] = k));
document.write('<pre>' + JSON.stringify(result, 0, 2) + '</pre>');