var myObj = [
{"a":"1", "b":"2"},
{"c":"3", "c":"4"},
{"d":"5", "e":"6"}
];
What is the best solution to pick one of the rows? I have this function below which convert the Object to array, but it returns indexes, though I need the full row.
var array = $.map(myObj, function(value, index) {
return value;
});
return array;
}
var myObj = [{
"a": "1",
"b": "2"
}, {
"c": "3",
"c": "4"
}, {
"d": "5",
"e": "6"
}];
var reformattedArray = myObj.map(function(value, index, array) {
return Object.values(value);
});
console.log(reformattedArray);
If the desired output is, for example:
[
"a",
"b"
]
Do:
var myObj = [
{"a":"1", "b":"2"},
{"c":"3", "c":"4"},
{"d":"5", "e":"6"}
];
var newArr = myObj.map(row => Object.keys(row));
console.log(newArr[0]);
Related
I am struggeling a bit to merge nested arrays into a new object.
I have an array with nested objects in it. The objects contain an array. Now I want to merge the entries of this array into a new object and assign a value to it. For example "false". Please see the example.
Current Structure:
const arr = [
{
baa: "some",
foo: ["1", "2", "3"],
},
{
baa: "some",
foo: [
"4",
"5",
"6",
"7",
],
},
]
Target Structure: merge "foo" entries into object and assign value.
const obj = {
1: false,
2: false,
3: false,
4: false,
5: false,
6: false,
7: false,
};
Fetch the array foo and iterate over using forEach and get the value and make it a property, You can do this using reduce.
const arr = [
{
baa: "some",
foo: ["1", "2", "3"],
},
{
baa: "some",
foo: ["4", "5", "6", "7"],
},
];
const result = arr.reduce((acc, curr) => {
const { foo } = curr;
foo.forEach((el) => (acc[el] = false));
return acc;
}, {});
console.log(result);
More declarative answer:
const arr = [
{
baa: "some",
foo: ["1", "2", "3"],
},
{
baa: "some",
foo: ["4", "5", "6", "7"],
},
];
// Build `obj` from `arr`
const obj = Object.fromEntries(
arr.map(val => val.foo)
.flat()
.map(
key => [key, false]
)
)
console.log(obj)
Side note: not compatible with legacy browsers such as IE11, see coverage here: https://caniuse.com/mdn-javascript_builtins_object_fromentries
While the other answers are correct I find them so much harder to read than a simple double loop.
let result = {}
for(let obj of arr){
for(let innerArrElem of obj.foo){
result[innerArrElem] = false
}}
}}
function populate(arr, value) {
return arr.reduce((acc, element) => {
element.foo.forEach((f) => acc[f] = false);
return acc;
}, {})
}
I have an array which has some objects and one of the propery of the object can have dupes viz. Account. Now i want to convert this array to map with key having Account's property value and the corresponding dupes should be stored as an array to that key in the map.
let arr = [];
arr.push({'Key':'1','Record':{'Account':'a','data':'A1'}});
arr.push({'Key':'2','Record':{'Account':'b','data':'123'}});
arr.push({'Key':'3','Record':{'Account':'a','data':'A2'}});
arr.push({'Key':'4','Record':{'Account':'a','data':'A3'}});
arr.push({'Key':'5','Record':{'Account':'c','data':'123'}});
const accIdMap= arr.reduce((map,obj) => (map[obj.Record.Account] = obj,map), {});
console.log(arr);
console.log(accIdMap);
So as of now the accIdMap just gets a one to one key-value mapping which is the last one pushed in the array i.e 4 but i want that the output map should have value as an array where ever the keys were duplicated. I tried reduction but that eliminates the duplicate values but i want the duplicate values as an corresponding array.
For example
As is output
{
"a": {
"Key": "4",
"Record": {
"Account": "a",
"data": "A3"
}
},
"b": {
"Key": "2",
"Record": {
"Account": "b",
"data": "123"
}
},
"c": {
"Key": "5",
"Record": {
"Account": "c",
"data": "123"
}
}
}
Desired OutPut (the keys which were duplicated should have the values added as an array)
{
"a": [{"Key": "4","Record": {"Account": "a","data": "A3"}},{
"Key": "3",
"Record": {
"Account": "a",
"data": "A2"
}
},{
"Key": "1",
"Record": {
"Account": "a",
"data": "A1"
}
}],
"b": {
"Key": "2",
"Record": {
"Account": "b",
"data": "123"
}
},
"c": {
"Key": "5",
"Record": {
"Account": "c",
"data": "123"
}
}
}
You can use reduce like this:
Check if the accumulator already has key with current a.Record.Account. If yes, push the current item in context to it. Else, add a.Record.Account as a key and then push the item to it.
const input = [{'Key':'1','Record':{'Account':'a','data':'A1'}},
{'Key':'2','Record':{'Account':'b','data':'123'}},
{'Key':'3','Record':{'Account':'a','data':'A2'}},
{'Key':'4','Record':{'Account':'a','data':'A3'}},
{'Key':'5','Record':{'Account':'c','data':'123'}}]
const output = input.reduce((acc, a) =>
((acc[a.Record.Account] = acc[a.Record.Account] || []).push(a), acc), {})
console.log(output);
Doing a check in the reduce function if the value exists already, then based on that you can do the following. If the Account already exists then check if the map has a array on that Account's key. If not create an array with the existing element and the current one by creating an empty array and pushing to that. If it is an array then just push to it. If the Account key doesn't exist then just set the value as the obj.
Update: Reordered the initialization of const m and added comment on code.
let arr = [];
arr.push({'Key':'1','Record':{'Account':'a','data':'A1'}});
arr.push({'Key':'2','Record':{'Account':'b','data':'123'}});
arr.push({'Key':'3','Record':{'Account':'a','data':'A2'}});
arr.push({'Key':'4','Record':{'Account':'a','data':'A3'}});
arr.push({'Key':'5','Record':{'Account':'c','data':'123'}});
const accIdMap= arr.reduce((map,obj) => {
if(map[obj.Record.Account]) { // the property exists and can be an array or the obj
if(!map[obj.Record.Account].length) { // means just the object. Creating an array then pushing the existing obj to it
const m = (map[obj.Record.Account]);
map[obj.Record.Account] = [];
map[obj.Record.Account].push(m);
}
map[obj.Record.Account].push(obj); // if it was an array this will push it to the existing array. If it wasn't the previous if have created and inserted old value and this line pushes to the new array
} else {
map[obj.Record.Account] = obj; // just putting the obj value as it wasn't a duplicate
}
return map;
}, {});
console.log(arr);
console.log(accIdMap);
This works like what you expected. take this result and match with your desired output.
let arr = [];
arr.push({ 'Key': '1', 'Record': { 'Account': 'a', 'data': 'A1' } });
arr.push({ 'Key': '2', 'Record': { 'Account': 'b', 'data': '123' } });
arr.push({ 'Key': '3', 'Record': { 'Account': 'a', 'data': 'A2' } });
arr.push({ 'Key': '4', 'Record': { 'Account': 'a', 'data': 'A3' } });
arr.push({ 'Key': '5', 'Record': { 'Account': 'c', 'data': '123' } });
var obj = {}
arr.map((e) => {
var filteredArr = arr.filter((f) => f.Record.Account == e.Record.Account)
if (filteredArr.length > 1)
obj[e.Record.Account] = filteredArr
else if (filteredArr.length != 0)
obj[e.Record.Account] = filteredArr[0]
})
console.log(JSON.stringify(obj))
I need to validate the JSON to ensure that if any property value is of type array, then it must have the same object types.
E.g consider the following example of valid JSON that should be accepted
{
"key1": "val_1",
"key_2": [{
"a": "b"
}, {
"c": "d"
}]
}
And following is the invalid JSON:
{
"key1": "val_1",
"key_2": [{
"a": "b"
}, {
"c": "d"
}, {
"f": 1
}]
}
Because {"f": 1} is different compare to first two nodes. First two nodes have string type of value and the "f" property value is numerical...hence it should be rejected.
I should be able to check and validate any array properties in JSON in this manner.
What is the best approach to implement this on client side javascript ?
A function to compare an array of objects, returning all which each value is of the selected type
function returnTypeMatched(arr,type){
var r = [];
if(type === undefined){type = 'String';}
for(var i=0,ilen=arr.length;i<ilen;i++){
var o = {},
item = arr[i],
keys = Object.keys(item);
for(var j=0,jlen=keys.length;j<jlen;j++){
var key = keys[j],
value = item[key];
if(arr[i][keys[j]].constructor.name === type){
o[key] = value;
}
}
if(Object.keys(o).length > 0){r.push(o);}
}
return r;
}
In your case
var myObject = {
"key1": "val_1",
"key_2": [{
"a": "b"
}, {
"c": "d"
}, {
"f": 1
}]
},
myKeys = Object.keys(myObject);
for(var i=0,ilen=myKeys.length;i<ilen;i++){
var key = myKeys[i],
value = myObject[key];
if(value.constructor.name === 'Array'){
var firstKeyType = value[0][Object.keys(value[0])[0]].constructor.name;
myObject[key] = returnTypeMatched(value,firstKeyType);
}
}
console.log(myObject);
/* Returns
{
"key1": "val_1",
"key_2": [{
"a": "b"
}, {
"c": "d"
}]
}
*/
I am learning to use underscore js. I grouped the array. But now i need split array.
I have a grouped JSON array. For example;
var arr = [{"key": "A", "value": ["erdem", "metin", "tamer", "hüseyin"]}]
I want this to be the result.
var arr = [{"key" : "A", "value" : "erdem"},{"key" : "A", "value" : "metin"},{"key" : "A", "value" : "tamer"},{"key" : "A", "value" : "hüseyin"}]
I'm happy if you show me how to do it.
Vanilla JS, without Underscore / lodash :
var arr = [
{"key": "A", "value": ["erdem", "metin", "tamer", "hüseyin"]},
{"key": "B", "value": ["foo", "bar"]}
];
// create modified array of objects
var result = arr.map(item => item.value.map(v => ({ key:item.key, value:v })) );
// print result
console.log( [].concat(...result) );
#forguta you can use this method to get your required output.
var arr = [{"key": "A", "value": ["erdem", "metin", "tamer", "hüseyin"]}]
_.map(arr,function(item){
var temp=[];
_.map(item.value, function(x){
temp.push({key: item.key, value: x});
});
return temp;
});
You can achieve the result without temp variable also (short form)
_.map(arr,function(item){
return _.map(item.value, function(x){
return {key: item.key, value: x};
});
});
How about reduce the main array and then concat each resulting array with a initial empty array
arr.reduce((i, o)=>i.concat(o.value.map(v=>({key: o.key, value: v}))), []);
var arr = [
{"key": "A", "value": ["erdem", "metin", "tamer", "hüseyin"]},
{"key": "B", "value": ["foo", "bar"]}
];
var res = arr.reduce((i, o)=>i.concat(o.value.map(v=>({key: o.key, value: v}))), []);
console.log(res);
I have a series of JSON entries:
[{"num": "1","name_A": "Alex" ,"name_B": "Bob"}, {"num": "2","name_A": "Anne" ,"name_B": "Barbra"}]
I am trying to convert this array of Objects as painlessly as possible into two objects - one with title name_A, and the second with the title name_B. Objects have to contain the title and an array of matching num-name pairs:
[{title: "name_A", names:[{"1", "Alex}, {"2", "Anne"}]}, {title:"name_B", names: [{"1", "Bob"}, {"2", "Barbra"}]}]
At first I tried simply to create two objects by reducing the array of object twice, once for name_A and second time for name_B and later glue everything together:
// get 'names' array
var name_A = objArray.reduce(function(memo, curr) {
memo.push({curr.num, curr.name_A})
return memo;
}, []);
But even this is failing. Why there is no push method for memo if I initialize reduce with an empty array?
And second question, am I on a right track or is there a better way to achieve this?
Comments inline, made a few minor corrections to the expectations.
var input = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }]
var output = input.reduce(function (a, b) {
// construct new objects and set their properties
var i = {};
i[b.num] = b.name_A;
var j = {};
j[b.num] = b.name_B;
// add them to our collection elements
a[0].names.push(i);
a[1].names.push(j);
return a;
// initializing our collection
}, [{ title: "name_A", names: [] }, { title: "name_B", names: [] }]);
// pretty print our output
console.log(JSON.stringify(output, null, " "))
var input = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }]
var output = input.reduce(function (a, b) {
// construct new objects and set their properties
var i = {};
i[b.num] = b.name_A;
var j = {};
j[b.num] = b.name_B;
// add them to our collection elements
a[0].names.push(i);
a[1].names.push(j);
return a;
// initializing our collection
}, [{ title: "name_A", names: [] }, { title: "name_B", names: [] }]);
so.log(output)
<pre id="output"></pre>
<script>
var so = {
log: function(o) {
document.getElementById("output").innerHTML = JSON.stringify(o, null, " ")
}
}
</script>
The problem with your code is that { curr.num, curr.name_A } is not a valid object, it's missing the property names. I've added properties num and name in my code below.
var name_A = [];
var name_B = [];
objArray.forEach(function(curr) {
name_A.push({num: curr.num, name: curr.name_a});
name_B.push({num: curr.num, name: curr.name_B});
});
var result = [
{ title: "name_A" }, names: name_A },
( title: "name_B" }, names: name_B }
];
Also, if you want to make an array out of the results of looping over an array, you should use .map rather than .reduce.
Assuming only property num is fixed. All other properties are treated as data, like name_A or name_B.
var a = [{ "num": "1", "name_A": "Alex", "name_B": "Bob" }, { "num": "2", "name_A": "Anne", "name_B": "Barbra" }],
result = [];
a.forEach(function (el) {
var num = el.num;
Object.keys(el).forEach(function (k) {
function tryFindIndexAndSetNames(aa, i) {
if (aa.title === k) {
result[i].names[num] = el[k];
return true;
}
}
if (k !== 'num' && !result.some(tryFindIndexAndSetNames)) {
var o = {};
o[num] = el[k];
result.push({ title: k, names: o });
}
});
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');