I have an array of objects, and and object with arrays as value. I'm trying to take the array from the object and add it as a value to a new key in the objects in the array. When you run the example below you see the object key is instead added as an array of its characters and I'm guessing I'm using Object.values() incorrectly?
So instead of the output being like;
{
"arrkey1": "arrvalue1",
"arrkey2": "arrvalue2",
"newStuff": [
"o",
"b",
"j",
"k",
"e",
"y",
"1"
]
}
How do I instead get what I want like;
{
"arrkey1": "arrvalue1",
"arrkey2": "arrvalue2",
"newStuff": [
"objValue1",
"objValue2",
"objValue3"
]
}
let arr1 = [
{
'arrkey1': 'arrvalue1',
'arrkey2': 'arrvalue2'
},
{
'arrkey3': 'arrvalue3',
'arrkey4': 'arrvalue4'
},
{
'arrkey5': 'arrvalue5',
'arrkey6': 'arrvalue6'
}
];
const obj1 = {
'objkey1': [
'objValue1',
'objValue2',
'objValue3'
],
'objkey2': [
'objValue4',
'objValue5',
'objValue6'
]
};
for (const item in obj1) {
for (let i = 0, x = arr1.length; i < x; i++) {
arr1[i].newStuff = Object.values(item);
}
}
console.log(arr1);
This example inserts a copy of obj1.objkey1 into each element of arr1:
let arr1 = [
{
'arrkey1': 'arrvalue1',
'arrkey2': 'arrvalue2'
},
{
'arrkey3': 'arrvalue3',
'arrkey4': 'arrvalue4'
},
{
'arrkey5': 'arrvalue5',
'arrkey6': 'arrvalue6'
}
];
const obj1 = {
'objkey1': [
'objValue1',
'objValue2',
'objValue3'
],
'objkey2': [
'objValue4',
'objValue5',
'objValue6'
]
};
const combined = arr1.map(item => ({newStuff: [...obj1.objkey1], ...item}));
console.log(combined);
Related
Given the following object, how can I loop through this object inorder to obtain both keys and values but only for the following keys:
"myName": "Demo"
"active": "Y"
"myCode": "123456789"
"myType": 1
let a = {
"values": {
"myName": "Demo",
"active": "Y",
"myCode": "123456789",
"myType": 1,
"myGroups": [
{
"myGroupName": "Group 1",
"myTypes": [
{
"myTypeName": "323232",
"myTypeId": "1"
}
]
},
{
"myGroupName": "Group 2",
"myTypes": [
{
"myTypeName": "523232",
"myTypeId": "2"
}
]
}
]
}
}
I have tried:
for (const [key, value] of Object.entries(a.values)) {
console.log(`${key}: ${value}`);
For}
but this will return all keys with their values.
You can use a dictionary (array) to contain the keys you want to extract the properties for, and then reduce over the values with Object.entries to produce a new object matching only those entries included in the dictionary.
let a = {
"values": {
"myName": "Demo",
"active": "Y",
"myCode": "123456789",
"myType": 1,
"myGroups": [{
"myGroupName": "Group 1",
"myTypes": [{
"myTypeName": "323232",
"myTypeId": "1"
}]
},
{
"myGroupName": "Group 2",
"myTypes": [{
"myTypeName": "523232",
"myTypeId": "2"
}]
}
]
}
}
const arr = [ 'myName', 'active', 'myCode', 'myType' ];
const out = Object.entries(a.values).reduce((acc, [key, value]) => {
if (arr.includes(key)) acc[key] = value;
return acc;
}, {});
console.log(out);
The best answer would be to set up an array of the desired keys and then iterate over that array instead of an array of the original object's entries. This is how you would achieve that:
let a = {
values: {
myName: "Demo",
active: "Y",
myCode: "123456789",
myType: 1,
myGroups: [{
myGroupName: "Group 1",
myTypes: [{
myTypeName: "323232",
myTypeId: "1"
}]
}, {
myGroupName: "Group 2",
myTypes: [{
myTypeName: "523232",
myTypeId: "2"
}]
}]
}
};
const keys = ['myName', 'active', 'myCode', 'myType'];
const cherryPick = (obj, keys) => keys.reduce((a,c) => (a[c] = obj[c], a), {});
console.log(cherryPick(a.values, keys));
The above example will work for many provided keys. If a key does not exist in the supplied object, its value will be undefined. If you want to only keep properties which have values, simply add an optional filter to the cherryPick() function, like this:
let test = {
a: 1,
b: 2
};
const keys = ['a', 'b', 'c'];
const cherryPick = (obj, keys, filter = 0) => keys.filter(key => filter ? obj[key] : 1).reduce((acc,key) => (acc[key] = obj[key], acc), {});
console.log('STORE undefined :: cherryPick(test, keys)', cherryPick(test, keys));
console.log('FILTER undefined :: cherryPick(test, keys, 1)', cherryPick(test, keys, true));
/* Ignore this */ .as-console-wrapper { min-height: 100%; }
If the fields key in a object is array, change the first value of arrays as a key value pair object in javascript.
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObj(obj) {
let objFields = {};
modifiedObj.fields.forEach(field => objFields[field] = field);
modifiedObj.fields= objFields;
return modifiedObj;
}
var result = this.newObject(obj)
Expected Output
{
item: "item",
sample: "sample"
}
Try this:
var obj =
[
{ id:1, fields:["item", "2", "list"]},
{ id:2, fields:["sample", "1", "check"]}
]
function newObject(obj) {
let objFields = {};
obj.forEach(e => {
if(e.fields && e.fields.length>0)
objFields[e.fields[0]] = e.fields[0];
});
return objFields;
}
var result = this.newObject(obj);
console.log(result);
Here is a functional approach that makes use of Object.assign(), spread operator, and Array.map() to create the object you need.
const input = [
{ id: 1, fields: ["item", "2", "list"] },
{ id: 2, fields: ["sample", "1", "check"] }
];
const process = (input) => (Object.assign(...input.map(({ fields }) => (
fields.length ? { [fields[0]]: fields[0] } : {}
))));
console.log(process(input));
Your snippet was close, you just needed to clean up the variable names, and then using map makes it a bit neater too:
const obj = [
{id: 1, fields: ["item", "2", "list"]},
{id: 2, fields: ["sample", "1", "check"]}
]
function newObj(inputArray) {
let outputObject = {};
inputArray.map(item => item.fields[0])
.forEach(field => outputObject[field] = field);
return outputObject;
}
var result = newObj(obj)
console.log(result)
Here is the nested array of object i am working on:
let arrayOfElements =
[
{
"username": "a",
"attributes":
{
roles:["Tenant-Hyd"],
groups:["InspectorIP", "InspectorFT"]
}
},
{
"username": "b",
"attributes":
{
roles:["Tenant-Pune"],
groups:["InspectorIP"]
}
},
{
"username": "c",
"attributes":
{
roles:["Tenant-Hyd"],
groups:["InspectorIP"]
}
}
];
I want users if they have Tenant-hyd role and also if groups has more then one string, then the user should be spit two.
so the final output should be:
arrayOfElements=[
{
"username": "a",
groups:"InspectorIP"
},
{
"username": "a",
groups:"InspectorFT"
},
{
"username": "c",
groups:"InspectorIP"
}
];
I would use a combination of filter and reduce array functions here.
filter would remove all elements where attributes.roles does not include 'Tenant-Hyd'.
reduce would then flatten the groups array.
const arrayOfElements =
[
{
"username": "a",
"attributes":
{
roles:["Tenant-Hyd"],
groups:["InspectorIP", "InspectorFT"]
}
},
{
"username": "b",
"attributes":
{
roles:["Tenant-Pune"],
groups:["InspectorIP"]
}
},
{
"username": "c",
"attributes":
{
roles:["Tenant-Hyd"],
groups:["InspectorIP"]
}
}
];
const filtered = arrayOfElements.filter(x => x.attributes.roles.includes('Tenant-Hyd'));
console.log('filtered', filtered);
const flattened = filtered.reduce((arr, current) => {
// create a new object for each group with the current username
const groups = current.attributes.groups.map(group => ({
username: current.username,
groups: group
}));
// push the new objects into the array
arr.push(...groups);
// return the array to the next iteration
return arr;
}, []);
console.log('flattened', flattened);
This demo sets up the initial array, runs the filter, and then runs the reduce. I have separated the steps out so you can see what's going on at each stage, but you could easily combine them.
const result = arrayOfElements
.filter(x => x.attributes.roles.includes('Tenant-Hyd'))
.reduce((arr, current) => {
arr.push(...current.attributes.groups.map(group => ({
username: current.username,
groups: group
})));
return arr;
}, []);
The reduce function
The reduce array function accepts a callback and an initial value. I am passing an empty array in as the initial value.
It is really a more powerful map. The source array will be iterated over, with the callback being called on each iteration. The value returned from the callback will be used as the accumulator on the next iteration.
// declare the callback
const callback = (arr, current) => {
// arr is the initial value on the first loop
// and whatever we return from this callback on subsequent loops
// add our flattened items to the accumulated array
arr.push(...current.attributes.groups.map(group => ({
username: current.username,
groups: group
})));
// return the accumulated array to the next iteration
return arr;
};
// loop over the items in myArray, calling the callback for each item
// pass an empty array in as the accumulator
myArray.reduce(callback, []);
A simpler alternative would be this:
const arr = [];
myArray.forEach(current => {
arr.push(...current.attributes.groups.map(group => ({
username: current.username,
groups: group
})));
});
This is easier to understand, but is not as concise as using reduce.
You can use the following snippet
let arrayOfElements = [{
"username": "a",
"attributes": {
roles: ["Tenant-Hyd"],
groups: ["InspectorIP", "InspectorFT"]
}
},
{
"username": "b",
"attributes": {
roles: ["Tenant-Pune"],
groups: ["InspectorIP"]
}
},
{
"username": "c",
"attributes": {
roles: ["Tenant-Hyd"],
groups: ["InspectorIP"]
}
}
];
var newa = [];
for (var i in arrayOfElements) {
if (arrayOfElements[i].attributes.roles[0] === 'Tenant-Hyd') {
for (var j in arrayOfElements[i].attributes.groups) {
var newObj = {
'username': arrayOfElements[i].username,
'groups': arrayOfElements[i].attributes.groups[j]
};
newa.push(newObj);
}
}
}
console.log(newa);
You can try this code
let arrayOfElements = [{
"username": "a",
"attributes": {
roles: ["Tenant-Hyd"],
groups: ["InspectorIP", "InspectorFT"]
}
},
{
"username": "b",
"attributes": {
roles: ["Tenant-Pune"],
groups: ["InspectorIP"]
}
},
{
"username": "c",
"attributes": {
roles: ["Tenant-Hyd"],
groups: ["InspectorIP"]
}
}
];
var res = [];
arrayOfElements.forEach(d => {
if (d.attributes.roles[0] == "Tenant-Hyd") {
d.attributes.groups.forEach(x => {
res.push({
"username": d.username,
"groups": x
})
})
}
});
console.log(res);
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);
I am trying to convert a JSON string in a Javascript object literal. I think it is possible with some loops, but i couldn't get it done. The target structure is shown below, "chartData".
Fiddle can be found here: http://jsbin.com/ajemih/13/edit
Here's the JSON data:
{
"1b":{
"allLoad":"130",
"loadMovement":"111",
"allMovement":"111"
},
"1a":{
"allLoad":"910",
"loadMovement":"671",
"allMovement":"280"
},
"systemLoad":"963"
}
This should it look like after the conversion:
chartData = [[['loadMovement', 111],
['allMovement', 120],
['allLoad', 130]],
[['Load+Move', 671],
['allMovement', 280],
['allLoad', 910]]];
I think this would work:
Working demo: http://jsfiddle.net/jfriend00/YmjDR/
var data = {
"1b":{
"allLoad":"130",
"loadMovement":"111",
"allMovement":"111"
},
"1a":{
"allLoad":"910",
"loadMovement":"671",
"allMovement":"280"
},
"systemLoad":"963"
};
var chartData = [];
for (var i in data) {
var item = data[i];
var outer = [];
// skip over items in the outer object that aren't nested objects themselves
if (typeof item === "object") {
for (var j in item) {
var temp = [];
temp.push(j);
temp.push(item[j]);
outer.push(temp);
}
}
if (outer.length) {
chartData.push(outer);
}
}
You could do something like this:
var chartData = []
for(var key in data) {
var properties = data[key];
if(typeof properties === "object") {
var array = [];
for(var propKey in properties) {
array.push([propKey, properties[propKey]])
}
chartData.push(array);
}
}
Check out the fiddle.
You need to map the data manually. Thats actually more a diligent but routine piece of work.
var jsonData = 'your json string';
Object.keys( jsonData ).map(function( key ) {
if( typeof jsonData[ key ] === 'object' ) {
return Object.keys( jsonData[ key ] ).sort(function( a, b ) {
return +jsonData[ key ][ a ] - +jsonData[ key ][ b ];
}).map(function( name ) {
return [ name, jsonData[ key ][ name ] ];
});
}
}).filter( Boolean );
The above code will sort each group by its numeric value and then map a new array in the required style. Since .map() possibly returns undefined values on non-object elements, we need to filter those out before or afterwards.
See http://jsfiddle.net/WjZB2/2/
I had similar problem.
My goal was to convert a list of strings into a valid format for http://ivantage.github.io/angular-ivh-treeview/
This was my starting point:
[
"A\\A1\\Test1",
"A\\A1\\Test2",
"A\\A2\\Test3",
"B\\Test4",
"B\\Test5",
"B\\B1\\Test6",
"B\\B1\\Test7",
"B\\B1\\Test8",
"C\\C1\\C1a\\Test9",
"C\\C1\\C1b\\Test10",
"C\\C2\\C2a\\Test11",
"C\\C2\\C2a\\Test12",
"C\\C2\\C2a\\Test13",
"C\\C3\\Test14",
"C\\Test15",
"C\\Test16"
]
And I needed following format:
[
{
"label": "Selected Tests",
"children": [
{
"label": "A",
"children": [
{
"label": "A1",
"children": [
{
"label": "Test1",
"value": true
},
{
"label": "Test2",
"value": true
}
]
},
{
"label": "A2",
"children": [
{
"label": "Test3",
"value": true
}
]
}
]
}
]
}
]
See my solution https://jsfiddle.net/ydt3gewn/