I have next object:
const types = {
sometypes: {
TYPE1: { name: 'type1', value: '1' },
TYPE2: { name: 'type2', value: '2' },
TYPE3: { name: 'type3', value: '3' },
},
TYPE4: { name: 'type4' },
};
how can I extract all name fields?
Expected result: ['type1','type2','type3','type4']
You can create a recursive function to loop through the object.
const types = {
sometypes: {
TYPE1: {
name: 'type1',
value: '1'
},
TYPE2: {
name: 'type2',
value: '2'
},
TYPE3: {
name: 'type3',
value: '3'
},
},
TYPE4: {
name: 'type4'
},
};
function extractNames(obj) {
let result = [];
Object.keys(obj).forEach(k => {
if (k == 'name') {
result.push(obj[k]);
} else if (typeof obj[k] == 'object') {
result.push(...extractNames(obj[k]));
}
});
return result;
}
console.log(extractNames(types));
Take entries of object and then map it accordingly.(I'm assuming your object is not nested)
var types = { sometypes: { TYPE1: { name: 'type1', value: '1' }, TYPE2: { name: 'type2', value: '2' }, TYPE3: { name: 'type3', value: '3' }, }, TYPE4: { name: 'type4' },};
var result = Object.entries(types).flatMap(([k,v])=> v.name ? v.name : Object.values(v).map(({name})=>name));
console.log(result);
This getNames function does it recursively.
const types = getSourceObject();
function getNames(obj, names){
const keys = Object.keys(obj);
keys.forEach( (key) => {
if(obj[key].name){ names.push(obj[key].name); }
else{ getNames(obj[key], names); }
});
}
const namesArr = [];
getNames(types, namesArr);
console.log(namesArr);
function getSourceObject(){
return {
sometypes: {
TYPE1: { name: 'type1', value: '1' },
TYPE2: { name: 'type2', value: '2' },
TYPE3: { name: 'type3', value: '3' }
},
TYPE4: { name: 'type4' }
};
}
Related
//this one is actual array
const data = [
{
name: 'shanu',
label: 'ak',
value: 1,
},
{
name: 'shanu',
label: 'pk',
value: 2,
},
{
name: 'bhanu',
label: 'tk',
value: 3,
},
];
>
//and this is the array that I want
let outPut =
[
{
name:'shanu',
label:['ak','pk'],
value:[1,2]
},
{
name:'bhanu',
label:['tk'],
value:[3]
}
]
You can use Array.prototype.reduce() like this:
const data = [
{
name: 'shanu',
label: 'ak',
value: 1,
},
{
name: 'shanu',
label: 'pk',
value: 2,
},
{
name: 'bhanu',
label: 'tk',
value: 3,
},
];
const output = data.reduce((prev, curr) => {
const tmp = prev.find((e) => e.name === curr.name)
if (tmp) {
tmp.label.push(curr.label)
tmp.value.push(curr.value)
} else {
prev.push({
name: curr.name,
label: [curr.label],
value: [curr.value],
})
}
return prev
}, [])
console.log(output)
Using the following array of objects, how do I just get the values for each of the key and save it into the desired name and value structure format mentioned below?
{
list: [
[
{
Desc: {
value: '7777 - Florida Hurricane'
},
DSTR_NR: {
value: '7777'
}
},
{
ST_NM: {
value: 'Alaska'
},
ST_CD: {
value: 'AK'
}
},
{
Desc: {
value: '7172 - Virginia Severe Storm(s)'
},
DSTR_NR: {
value: '7172'
}
},
{
ST_NM: {
value: 'Florida'
},
ST_CD: {
value: 'FL'
}
},
{
Desc: {
value: '7002 - Maryland Hurricane'
},
DSTR_NR: {
value: '7002'
}
},
{
ST_NM: {
value: 'Louisiana'
},
ST_CD: {
value: 'LA'
}
}
]
]
}
Desired format that I need regardless if the api returns disaster related data or states related data. I just need to store the data values in name/value pair like the following:
{
list: [
{
name: '7777',
value: '7777 - Florida Hurricane'
},
{
name: 'AK',
value: 'Alaska'
},
...
]
}
Here's my current code:
let newData = {}
list.forEach((value) => {
Object.keys(value).forEach((key) => {
if(newData[key] === undefined){
newData[key] = [value[key]]
} else {
newData[key].push(value[key])
}
})
});
You can map through the object like so
const res = {
list: [
[
{
Desc: {
value: '7777 - Florida Hurricane'
},
DSTR_NR: {
value: '7777'
}
},
{
ST_NM: {
value: 'Alaska'
},
ST_CD: {
value: 'AK'
}
},
{
Desc: {
value: '7172 - Virginia Severe Storm(s)'
},
DSTR_NR: {
value: '7172'
}
},
{
ST_NM: {
value: 'Florida'
},
ST_CD: {
value: 'FL'
}
},
{
Desc: {
value: '7002 - Maryland Hurricane'
},
DSTR_NR: {
value: '7002'
}
},
{
ST_NM: {
value: 'Louisiana'
},
ST_CD: {
value: 'LA'
}
}
]
]
}
const list = res.list[0];
const format = list.map(i => {
const items = Object.values(i);
const newItem = {}
newItem.name = items[1].value;
newItem.value = items[0].value;
return newItem
})
console.log(format)
If the data contains always the value first and the name second, you can do this:
// let response = { list: [...] }
let result = {
list: []
};
response.list.forEach(sublist => {
sublist.forEach(elem => {
let keys = Object.keys(elem);
result.list.push({
name: elem[ keys[1] ].value,
value: elem[ keys[0] ].value,
})
});
})
console.log("RESULT: ", result);
i am trying to filter some objects that i have in an array, but inside this array i have some objects that i would like to collect and concat as array, i am working arround but i couldn't reach the expected output
MY ARRAY
[
{
_id: '60c0c5d7f5b87a1604d3d555',
name: 'Colors'
attribute: {
value: 'red'
_id: '60c0c5d7f5b87a1604d3d544',
}
},
{
_id: '60c0c5d7f5b87a1604d3d555',
name: 'Colors'
attribute: {
value: 'blue'
_id: '60c0c5d7f5b87a1604fsd33',
}
},
{
_id: '60c0c5d7f5b87a1604d3f566',
name: 'Sizes'
attribute: {
value: 'M'
_id: '60c0c5d7f5b87a1604d3d522',
}
},
{
_id: '60c0c5d7f5b87a1604d3f566',
name: 'Sizes'
attribute: {
value: 'L'
_id: '60c0c5d7f5b87a1604d3d512',
}
}
]
EXPECTED OUTPUT
[
{
_id: '60c0c5d7f5b87a1604d3d555',
name: 'Colors'
attributes:[
{
value: 'red'
_id: '60c0c5d7f5b87a1604d3d544',
},
{
value: 'blue'
_id: '60c0c5d7f5b87a1604fsd33',
}
]
},
{
_id: '60c0c5d7f5b87a1604d3f566',
name: 'Sizes'
attributes: [
{
value: 'M'
_id: '60c0c5d7f5b87a1604d3d522',
},
{
value: 'L'
_id: '60c0c5d7f5b87a1604d3d512',
}
]
}
]
Any help is appreciated, thanks in advance!
You can use array#reduce and object.values() to group your array based on _id.
const data = [ { _id: '60c0c5d7f5b87a1604d3d555', name: 'Colors', attribute: { value: 'red', _id: '60c0c5d7f5b87a1604d3d544', } }, { _id: '60c0c5d7f5b87a1604d3d555', name: 'Colors', attribute: { value: 'blue', _id: '60c0c5d7f5b87a1604fsd33', } }, { _id: '60c0c5d7f5b87a1604d3f566', name: 'Sizes', attribute: { value: 'M', _id: '60c0c5d7f5b87a1604d3d522', } }, { _id: '60c0c5d7f5b87a1604d3f566', name: 'Sizes', attribute: { value: 'L', _id: '60c0c5d7f5b87a1604d3d512', } } ],
result = Object.values(data.reduce((r, {_id, name, attribute}) => {
r[_id] = r[_id] || { _id, name, attributes: []};
r[_id].attributes.push(attribute);
return r;
},{}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Can try to create hashmap list, with id+name identifier and value attribute list. I think that this way you will be able to concatenate and have the expected output.
function concatArray(idTextAreaOut){
var i =0,j = 0;
var array = [ { _id: '60c0c5d7f5b87a1604d3d555', name: 'Colors', attribute: { value: 'red', _id: '60c0c5d7f5b87a1604d3d544', } }, { _id: '60c0c5d7f5b87a1604d3d555', name: 'Colors', attribute: { value: 'blue', _id: '60c0c5d7f5b87a1604fsd33', } }, { _id: '60c0c5d7f5b87a1604d3f566', name: 'Sizes', attribute: { value: 'M', _id: '60c0c5d7f5b87a1604d3d522', } }, { _id: '60c0c5d7f5b87a1604d3f566', name: 'Sizes', attribute: { value: 'L', _id: '60c0c5d7f5b87a1604d3d512', } } ];
var arrayConcat = [];
for(i = 0; i < array.length;i++){
var element = array[i];
var key = element._id+element.name;
var finded = false;
for(j = 0; j < arrayConcat.length;j++){
var otherElement = arrayConcat[j];
var keyOther = otherElement._id+otherElement.name;
if(key == keyOther){
if(!Array.isArray(otherElement.attribute)){
var temp = otherElement.attribute;
otherElement.attribute = [];
otherElement.attribute.push(temp);
}
otherElement.attribute.push(element.attribute);
finded = true;
}
}
if(!finded){
arrayConcat.push(element);
}
}
$('#'+idTextAreaOut).val(JSON.stringify(arrayConcat));
}
I have two arrays, and now I want to merge the two arrays.
The first array:
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
Two arrays:
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
I want to merge them into this:
var data3 = [
{name: 'aa', value: 1},
{name: 'bb', value: 2},
{name: 'cc', value: 3},
{name: 'dd', value: 0},
{name: 'ee', value: 0}
];
console.log(data3)
At present, my experience is not enough. Please help me solve this problem.
Thanks in advance.
You can try following based on following assumptions
data2 is a collection of names and expecting its length to be always more than length of data
Order of objects can be different
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
// Iterate over the names array
var data3 = data2.map(({name}) => {
// get the matched object in data corresponding to the name
var match = data.find((obj) => obj.name === name);
// if found, return value else default value to 0
return match ? match : {name, value : 0};
});
console.log(data3);
If the input arrays are indeed in order like that, then a simple .map would suffice:
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
const output = data2.map(({ name }, i) => ({ name, value: data[i] ? data[i].value : 0 }));
console.log(output);
Create an object lookup for each name using array#reduce. Extract all the values using the Object.values() from the object lookup.
const data1 = [ { name: 'aa', value: 1 }, { name: 'bb', value: 2 }, { name: 'cc', value: 3 } ],
data2 = [ { name: 'aa' }, { name: 'bb' }, { name: 'cc' }, { name: 'dd' }, { name: 'ee' } ],
result = Object.values([data1, data2].reduce((r,a) => {
a.forEach(({name, value = 0}) => {
r[name] = name in r ? r[name] : {name, value};
});
return r;
},{}));
console.log(result);
You can array#concat both the arrays and using array#reduce create an object lookup and then get all the values using the Object.values().
const data1 = [ { name: 'aa', value: 1 }, { name: 'bb', value: 2 }, { name: 'cc', value: 3 } ],
data2 = [ { name: 'aa' }, { name: 'bb' }, { name: 'cc' }, { name: 'dd' }, { name: 'ee' } ],
result = Object.values(data1.concat(data2).reduce((r,{name, value=0}) => {
r[name] = name in r ? r[name] : {name, value};
return r;
},{}));
console.log(result);
var data = [
{ name: 'aa', value: 1 },
{ name: 'bb', value: 2 },
{ name: 'cc', value: 3 }
];
var data2 = [
{ name: 'aa' },
{ name: 'bb' },
{ name: 'cc' },
{ name: 'dd' },
{ name: 'ee' }
];
let output = new Array(data2.length).fill(data2.length).map(v => new Object());
// Logic
data.forEach((val2)=> {
data2.forEach((val, i)=> {
if (val.name == val2.name){
output[i]["name"] = val.name
output[i]["value"] = val2.value
} else{
output[i]["name"] = val.name
}
})
})
output.map((val,i) => {
if (!val.hasOwnProperty("value")){
console.log(val)
val["value"] = 0
}
})
console.log("------Your Expected Format", output)
I'm trying to build a JS function to convert the data structure in the form of
'start' to the form of 'expected'.
Using JS map() method, how would I do this for the following associative array-
const start = {
Clients: {
171: { id: 171, name: 'John Smith', active: false },
172: { id: 172, name: 'Jacob Jacobson', active: true },
1441: { id: 1441, name: 'Eric Ericsson', active: true },
},
Caregivers: {
1: { id: 1, name: 'John Johnson', active: true },
37: { id: 37, name: 'James Jameson', active: false },
15: { id: 15, name: 'Aaron Aaronson', active: true },
},
Doctors: {
1147: { id: 1147, name: 'Doc Docson', active: true },
},
Hospitals: {
115: { id: 115, active: false, name: "St. Mary's" },
},
Applicants: {
17345: { id: 17345, name: 'Bob Bobson', active: true },
17346: { id: 17346, name: 'Jeff Jeffson', active: false },
17347: { id: 17347, name: 'Frank Frankson', active: true },
17348: { id: 17348, name: 'Bill Billson', active: true },
},
};
needs to be converted to-
const expected = [
{ label: 'Bill Billson', value: 17348, group: 'Applicants' },
{ label: 'Bob Bobson', value: 17345, group: 'Applicants' },
{ label: 'Frank Frankson', value: 17347, group: 'Applicants' },
{ label: 'Aaron Aaronson', value: 15, group: 'Caregivers' },
{ label: 'John Johnson', value: 1, group: 'Caregivers' },
{ label: 'Eric Ericsson', value: 1441, group: 'Clients' },
{ label: 'Jacob Jacobson', value: 172, group: 'Clients' },
{ label: 'Doc Docson', value: 1147, group: 'Doctors' },
];
.map() can't be used directly on Objects; instead you'll need to use Object.keys
const start = {
Clients: {
171: { id: 171, name: 'John Smith', active: false },
172: { id: 172, name: 'Jacob Jacobson', active: true },
1441: { id: 1441, name: 'Eric Ericsson', active: true }
},
Caregivers: {
1: { id: 1, name: 'John Johnson', active: true },
37: { id: 37, name: 'James Jameson', active: false },
15: { id: 15, name: 'Aaron Aaronson', active: true }
},
Doctors: {
1147: { id: 1147, name: 'Doc Docson', active: true }
},
Hospitals: {
115: { id: 115, active: false, name: "St. Mary's" }
},
Applicants: {
17345: { id: 17345, name: 'Bob Bobson', active: true },
17346: { id: 17346, name: 'Jeff Jeffson', active: false },
17347: { id: 17347, name: 'Frank Frankson', active: true },
17348: { id: 17348, name: 'Bill Billson', active: true }
}
};
// Get an array of properties in 'start'
// then use Array.reduce() to loop over each item
const expected = Object.keys(start).reduce( (res, gKey) => {
// gKey = 'group' name
// gVal = 'group' value
let gVal = start[gKey];
// loop over each item in the 'group'
Object.keys(gVal).forEach(iKey => {
// iKey = 'group.item' name
// iVal = 'group.item' value
let iVal = gVal[iKey];
// if the value's .active property is truthy
if (iVal.active) {
// format the result as desired and add it to the result array
res.push({
label: iVal.name,
value: iKey,
group: gKey
});
}
});
// return the result array
return res;
// start the .reduce() with an empty array
}, []);
console.log(expected);
To loop over an object, you can either use a for ... in loop, or use Object.keys to get an array of keys. For ... in will include inherited properties, so you may need to manually filter them out. Object.keys only returns own properties, so there's no need to do the filtering (but it also isn't appropriate if you need inherited properties)
Example with for ... in:
for (var prop in start) {
if (start.hasOwnProperty(prop)) {
// logs out 'Clients', then 'Caregivers', then 'Doctors', then 'Hospitals', then 'Applicants'
console.log(prop);
}
}
Example with Object.keys:
//produces array ['Clients', 'Caregivers', 'Doctors', 'Hospitals', 'Applicants']
var keys = Object.keys(start);
So if you wanted to use .map, you can start with this, and fill it in to do whatever you desire:
Object.keys(start)
.map(key => {
//do something with start[key]
//perhaps you could get Object.keys(start[key]) and loop over that as well.
});
My solution without 'forEach':
function transform(data) {
Object.entries(data).map(item => Object.values(item[1])
.map(i => i.group = item[0]))
.reduce(( acc, cur ) => acc.concat(cur), [])
.filter(item => item.active === true)
.sort((a, b) => a.group - b.group)
.map(item => {
let expected = {};
expected.label = item.name;
expected.value = item.id;
expected.group = item.group;
});
return expected;
}