Split array by specific requirements - javascript

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);

Related

Javascript Convert an array to map keyed with the array property and store the corresponding duplicate key values as array

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))

How to define id of Object generated from 2D Array

I have generated an object from 2D array.
And then, how to define unique id through each object?
"?" in the following code needs to edit.
data = [
["a", "b", "c"],
["a", "b"]
]
for (i in data) {
data[i] = data[i].map(c => ({id: ?, char:c}) )
}
console.log(data)
The following result format is assumed.
[
0: {
0:{
"id": "?",
"char": "a"
},
1:{
"id": "?",
"char": "b"
},
2:{
"id": "?",
"char": "c"
}
},
1: {
0:{
"id": "?",
"char": "a"
},
1:{
"id": "?",
"char": "b"
}
}
]
I thought iterating, but it seems like to needs to flatten the object,
so I could not use it because I did not want to change the format of the original object.
You can create count variable to make the id
data = [
["a", "b", "c"],
["a", "b"]
]
let count = 0;
for (let i in data) {
data[i] = data[i].map(c => {
count ++;
return {id: count, char:c}
} )
}
console.log(data)
You could map single objects inside and assign the arrays to an object. Take the same approach for the outer array.
var data = [["a", "b", "c"], ["a", "b"]],
result = Object.assign(
{},
data.map(a => Object.assign(
{},
a.map(char => ({ id: '?', char }))
))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Because you want objects rather than arrays, you won't be able to use .map. Because you have both parent objects and nested objects, you might use reduce twice:
const data = [
["a", "b", "c"],
["a", "b"]
];
const output = data.reduce((a, arr, i) => {
a[i] = arr.reduce((obj, char, j) => {
obj[j] = { char, id: '?' };
return obj;
}, {});
return a;
}, {});
console.log(output);

Selecting data from an array as an Object

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]);

Refactoring object into a flat array

I have an object like this.
{Brunch: 2, Kimchi: 1}
I need to refactor it into an an array/object
[{
"label" : "Brunch",
"value" : 2
},
{
"label" : "Kimchi",
"value" : 1
}]
You can use Object.keys() and map() to get desired result.
var obj = {
Brunch: 2,
Kimchi: 1
}
var result = Object.keys(obj).map(function(k) {
return {
"label": k,
"value": obj[k]
}
})
console.log(result)
The simplest way:
var result = Object.keys(input).map(key => ({
label: key,
value: input[key],
}));

javascript - how do i flatten an array of json into an array of a particular json attributes?

So lets say i have an array like so
[
{name: "a", happyName: "bob" }
, {name: "b", happyName: "cow" }
, {name: "c", happyName: "moo" }
, {name: "d", happyName: "jen" }
]
What is the most efficient manner to flatten it to an array like so:
[ "a","b","c","d"]
(or alternatively to get only the happyName in the values instead - to be precise, i suppose, how would i flatten some given array into an array of some given named json attribute?)
NB this is javascript only, no JQuery etc stuff please.
This is a good use case for map():
var names = theArray.map(function(item) {
return item.name;
});
var happyNames = theArray.map(function(item) {
return item.happyName;
});
If you have to do this a lot, it's quite easy to create a helper:
var names = values(theArray, 'name'),
happyNames = values(theArray, 'happyName');
function values(arr, attr) {
return arr.map(function(item) {
return item[attr];
});
}
You can use Array.map for that
var names = arr.map(function(obj) {
return obj.name;
});
FIDDLE
var arr = [
{name: "a", happyName: "bob" }
, {name: "b", happyName: "cow" }
, {name: "c", happyName: "moo" }
, {name: "d", happyName: "jen" }
]
var names = arr.map(function(e) { return e.name } )
.map() is a cool method, but keep in mind it's not compatible with legacy IE (<9). If you want something that'll work everywhere, go for this:
var arrayOfObjects = [
{name: "a", happyName: "bob" },
{name: "b", happyName: "cow" },
{name: "c", happyName: "moo" },
{name: "d", happyName: "jen" }
],
array = [],
i = 0,
len = arrayOfObjects.length;
for(;i<len;i++) {
array.push(arrayOfObjects[i].name);
}
// output => [ "a","b","c","d"]

Categories

Resources