I'm making Ajax calls to a page in ASP.NET Core 3.1.
The response is a JsonResult whose Value property is an instance of a custom class, itself containing various string and collection properties.
One of these collections is a Dictionary<string, string>, which I can then access in JavaScript along the following lines:
var dictionary = response.DictionaryObj;
for (key in dictionary) {
DoSomeStuff(key, dictionary[key]);
}
However another of these collections requires a non-unique 'key', and is currently a List<KeyValuePair>
This ends up in JavaScript as an array of objects, which I can access like this:
var kvps = response.KvpList;
for (i = 0; i < kvps.length; i++) {
var kvp = kvps[i];
DoSomeMoreStuff(kvp.key, kvp.value);
}
The latter seems far less elegant - is there a way of packaging up the KeyValuePairs in a way that would let me use the former syntax?
For Dictionary<string, string> you can use Object.entries()
For List<KeyValuePair> object destructuring
const dictionaryObj = {
a: 'somestring',
b: 42,
};
for (const [key, value] of Object.entries(dictionaryObj)) {
console.log(`${key}: ${value}`); // DoSomeStuff(key, value)
}
console.log('===========================================');
const kvpList = [
{ key: '1', value: 'v1' },
{ key: '2', value: 'v2' },
{ key: '3', value: 'v3' },
];
for (const { key, value } of kvpList) {
console.log(`${key}: ${value}`); // DoSomeMoreStuff(key, value)
}
If you have an object and you want to iterate through its properties, then we can use Object.entries method to get an array of a given object's own enumerable string-keyed property [key, value] pairs, and then just use loop foreach:
let input = { "workType": "NDB To Nice", "priority": 5, "name": "Joseph", "lastName": "Skeet" }
const fooFunctiion = (key, value) => {
console.log(`key: ${key}, value ${value}` )
}
Object.entries(input).forEach(([k, v]) => {
fooFunctiion(k, v)
});
If you have an array of objects, then you can use foreach method:
let input = [
{ "workType": "NDB To Nice", "priority": 5 },
{ "workType": "PDAD", "priority": 0 },
{ "workType": "PPACA", "priority": 0 },
{ "workType": "Retrigger", "priority": "5" },
{ "workType": "Special Intake Request Intake", "priority": "7" }
];
const fooFunction = (obj, index) => {
console.log('obj: ', obj, index )
}
input.forEach((obj, ind) =>
fooFunction(obj, ind)
);
Related
I have an array like so with a single object inside:
FirstArray = [{
"category": "None",
"ARFE": 553.5,
"BV": 900,
"RF rfeer": 0,
.....
}]
I want to convert it so that every key-value pair (where the value is a number) in the object is in its own object like the following:
NewArray = [{
name: "ARFE",
value: 553.05
}, {
name: "BV",
value: 900
}, {
name: "RF rfeer",
value: 0
}, .....]
Here, each key was assigned a new key called name, and the value for the original key was assigned a new key called value. Those pairs are then put into their own object inside the array.
Note that "category": "None" is not its own object in the array since "None" is non-numerical.
It's also important to note that there could be many key-value pairs, so it's not just limited to the items above (e.g., "ARFE": 553.5, etc.)
What I have so far:
I know you can separate a single object into multiple objects:
NewArray = Object.entries(FirstArray).reduce((prev, [og, nw]) => {
let [name, value] = og.match(/\D+|\d+$/g)
prev[value] = { ...(prev[value] || {}), [name]: nw }
return prev;
}, {})
I also know how that you can create a new object with new keys like so:
NewArray = Object.assign(
...Object.entries(FirstArray).map(([key, value]) => ({ [key]: name }))
);
However, I'm having trouble putting everything together. How would I be able to achieve NewArray from FirstArray?
You were pretty close. All you needed to do is specify the name:
const data = {
"category": "None",
"ARFE": 553.5,
"BV": 900,
"RF rfeer": 0
};
const result = Object
.entries(data)
.filter(([_, value]) => typeof value === 'number')
.map(([key, value]) => ({ name: key, value }));
console.log(result);
Also, if you don't want { "name": "category", "value": "None" } to be included in the result, you can just filter it:
const result = Object
.entries(data)
.filter(([ key ]) => key !== 'category')
.map(([key, value]) => ({ name: key, value }));
Object.entries on array has no sense at all, use it on the object
const FirstArray = [{
"category": "None",
"ARFE": 553.5,
"BV": 900,
"RF rfeer": 0,
}]
const newObject = Object.entries(FirstArray[0]).reduce((array, [key, value]) => {
return [...array, {
name: key,
value
}]
}, [])
console.log(newObject)
reduce is not the right way to go. Simply use map:
Object.entries(FirstArray[0])
.filter(x => !isNaN(x[1])) // filter out non-numeric values
.map(([name, value]) => ({name, value}))
I'm trying to reduce and array of object(key-value) to one object(key-value).
I'm working with a json object injavascript
I have this:
"relations":
[
{"609e598ad32e90519043f09f": "609d8b78cf7bb100045fc593"},
{"609e5945d32e90519043f09e": "609d8b78cf7bb100045fc593"},
{"609e58b496d43235884e788f": "609d8b78cf7bb100045fc593"},
{"609e57e3e1560e58245544f4": "609d8de9575b49000466e358"}
],
And below is my expected result:
"relations":
{
"609e598ad32e90519043f09f":"609d8b78cf7bb100045fc593",
"609e5945d32e90519043f09e":"609d8b78cf7bb100045fc593",
"609e58b496d43235884e788f":"609d8b78cf7bb100045fc593",
"609e57e3e1560e58245544f4":"609d8de9575b49000466e358"
}
How can I achieve this result?
You can use for..in loop to get the key-value and using reduce to store it into an object. Then you can assign it to relations property.
let obj = {
relations: [
{ "609e598ad32e90519043f09f": "609d8b78cf7bb100045fc593" },
{ "609e5945d32e90519043f09e": "609d8b78cf7bb100045fc593" },
{ "609e58b496d43235884e788f": "609d8b78cf7bb100045fc593" },
{ "609e57e3e1560e58245544f4": "609d8de9575b49000466e358" },
],
};
const result = obj.relations.reduce((acc, curr) => {
for (let key in curr) {
acc[key] = curr[key];
}
return acc;
}, {});
obj.relations = result;
console.log(obj);
You can also clone the object and change only the relations key using object destructuring
let obj = {
name: "test",
relations: [
{ "609e598ad32e90519043f09f": "609d8b78cf7bb100045fc593" },
{ "609e5945d32e90519043f09e": "609d8b78cf7bb100045fc593" },
{ "609e58b496d43235884e788f": "609d8b78cf7bb100045fc593" },
{ "609e57e3e1560e58245544f4": "609d8de9575b49000466e358" },
],
};
const result = obj.relations.reduce((acc, curr) => {
for (let key in curr) {
acc[key] = curr[key];
}
return acc;
}, {});
const cloneWithChanges = { ...obj, relations: result };
console.log(cloneWithChanges);
I have an Array that contain some keys/values one of the values is an array I want combining the value of array from all recorded that have same key in my Array.
Below is an Simple Example to demonstrate, I am not able to construct its logic so seeking help in building a logic to it.
[{"somekey":"Some Value Pushed"},{"somekey":"Second Value"}]
I want Result Like,
[{"somekey":["Some Value Pushed","Second Value"]}]
The reduce() function of Array Object in JavaScript can merge any array into a single Object.
I wrote a single-line code to solve this problem.
I updated result with the array.
const arr = [{
somekey: "Some Value Pushed",
},
{
somekey2: "Second Value2",
},
{
somekey: "Some Value Pushed",
},
{
somekey2: "Second Value3",
},
{
somekey3: "",
},
{},
];
const ansObj = arr.reduce(
(prv, cur) => {
Object.entries(cur).forEach(([key, v]) => key in prv ? prv[key].push(v) : (prv[key] = [v]));
return prv;
}, {}
)
const ansArray = Object.entries(ansObj).map(([key, value])=>({[key]:value}));
console.log(ansArray);
You can try something like this:
var array = [{
name: "foo1",
value: "val1"
}, {
name: "foo1",
value: ["val2", "val3"]
}, {
name: "foo2",
value: "val4"
}];
var output = [];
array.forEach(function(item) {
var existing = output.filter(function(v, i) {
return v.name === item.name;
});
if (existing.length) {
var existingIndex = output.indexOf(existing[0]);
output[existingIndex].value = output[existingIndex].value.concat(item.value);
} else {
if (typeof item.value === 'string')
item.value = [item.value];
output.push(item);
}
});
Or, another option using Lodash
function mergeNames (arr) {
return _.chain(arr).groupBy('name').mapValues(function (v) {
return _.chain(v).pluck('value').flattenDeep();
}).value();
}
Maybe something like:
const data = [
{"somekey":"Some Value Pushed"},
{"somekey":"Second Value", "otherkey": 1},
{"otherkey": 2}
];
const merge_and_group = (obj1, obj2) =>
Object.entries(obj2).reduce(
(acc, [key, val]) => {
acc[key] ??= [];
acc[key].push(val);
return acc;
},
obj1
);
const res = data.reduce(merge_and_group, {});
console.log(res);
const arr = [{
"somekey": "Some Value Pushed"
}, {
"somekey2": "Second Value2"
}, {
"somekey": "Some Value Pushed"
}, {
"somekey2": "Second Value3"
}]
const newarr = {}
arr.forEach(obj => {
for (const [key, value] of Object.entries(obj)) {
if (newarr[key]) newarr[key].push(value)
else newarr[key] = [value]
}
})
console.log(newarr)
Array.prototype.reduce() is a possible option.
the reduce() method executes a reducer function which is provided as an input on each element of the array and returning a single output value.
const array = [{"somekey":"Some Value Pushed"},{"somekey":"Second Value"}];
const res = array.reduce((acc, el) => {
const [key, value] = Object.entries(el)[0];
(acc[key] || (acc[key] = [])).push(value);
return acc;
}, {});
console.log(res)
Assuming each element of your array is an object with a single key.
const array = [
{ somekey: "Some Value Pushed" },
{ somekey: "Second Value" },
{ foo: "bar" },
{ foo: "baz" },
{ somekey: "Third Value" },
];
const result = [];
array.forEach(el => {
let [key, value] = Object.entries(el)[0];
for (let el of result) if (key in el) {
el[key].push(value);
return;
}
result.push({ [key]: [value] });
});
console.dir(result);
If your array has only "somekey" as keys then you can use map method as following:
const array = [{"somekey":"Some Value Pushed"},{"somekey":"Second Value"}];
const valuesArray = array.map(obj => obj.somekey);
result = [{"somekey":valuesArray}];
console.log(result)
If your array has other keys along with "somekey" and you like to separate values corresponding to only "somekey" then try the following:
const array = [{"somekey":"Some Value Pushed"},{"somekey":"Second Value"}, {"otherkey":"other Value"}];
const filteredArray = array.filter((obj) => {
return "somekey" in obj
}, []);
const valuesArray = filteredArray.map(obj => obj.somekey);
result = [{"somekey":valuesArray}];
console.log(result)
I am trying to convert a nested array to an object, I made several attempts but without success.
these are the data i have
[
['key1', { childKey1: "text" }, { childKey2: "text" }],
['key2', { childKey1: "text" }, { childKey2: "text" }]
]
this is the data i need
{
key1: {
childKey1: "text",
childKey2: "text"
},
key2: {
childKey1: "text",
childKey2: "text"
}
}
Map the data to entries - [[key, value], [key, value]]. Use destructuring to get the key (the 1st item in a sub-array), and rest syntax to get an array of objects. Merge the array of objects by spreading the array of objects into Object.assign() to get the value. Use Object.fromEntries() to convert the entries to an object.
const data = [['key1', {childKey1: "text"}, {childKey2: "text"}], ['key2', {childKey1: "text"}, {childKey2: "text"}]]
const result = Object.fromEntries(data.map(
([k, ...v]) => [k, Object.assign({}, ...v)]
))
console.log(result)
You may try reduce to achieve such task. You could do something like this:
const data = [
["key1", { childKey1: "text" }, { childKey2: "text" }],
["key2", { childKey1: "text" }, { childKey2: "text" }]
];
function dataToJSON(data) {
return data.reduce((acc, current) => {
const [key, ...values] = current;
acc[key] = Object.assign({}, ...values);
return acc;
}, {});
}
console.log(dataToJSON(data));
Works perfect for any number of children. You have to be careful with repeated keys not to overwrite a previous one.
.reduce() method is another way to approach this.
const arr = [['key1', {childKey1: "text"}, {childKey2: "text"}], ['key2', {childKey1: "text"}, {childKey2: "text"}]];
const newArr = arr.reduce((accumulator, currVal) => {
const [key, ...values] = currVal; // destruct array and separate key from all other values
accumulator[key] = Object.assign({}, ...values); // assign values to your final object, using the key extracted above
return accumulator;
}, {});
console.log(newArr);
I know this was already answered, but here's my attempt at it:
let jsonArray = [['key1', {childKey1: "text"}, {childKey2: "text"}], ['key2', {childKey1: "text"}, {childKey2: "text"}]];
let newJson = {};
for(var i=0; i<jsonArray.length; i++){
newJson[jsonArray[i][0]] = Object.assign({}, ...jsonArray[i].slice(1));
}
console.log(newJson);
I have several objects and I want to create another one that will have keys from a particular array (const props = []), and values from those objects - if it only exists in those objects, but if not - I want to push null or some other fake values.
My code:
const props = ["name", "price", "qty", "category"]
let len = props.length;
const obj_1 = {
name: "Product_1",
price: 120,
category: 'phone'
}
const obj_2 = {
name: "Product_2",
price: 7893,
category: 'program_eq',
qty: 5
}
const final_obj = {
name: ["Product_1", "Product_2"],
price: [120, 7893],
category: ["phone", "program_eq"],
qty: [null, 5]
}
I have spent lots of time with this problem and have some solution - but it gives me only the first object.
I am using lodash/map and it helps me to work with different type of collection.
You can see my solution bellow:
const final_obj = {};
const props = ["name", "price", "qty", "category"];
let len = props.length;
const obj = {
c1s6c156a1cascascas: {
item: {
name: "Product_1",
price: 120,
category: "phone"
}
},
c454asc5515as41cas78: {
item: {
name: "Product_2",
price: 7893,
category: "program_eq",
qty: 5
}
}
};
_.map(obj, (element, key) => {
console.log(element.item);
while (len) {
let temp = props.shift();
let tempData = [];
if (element.item.hasOwnProperty([temp])) {
tempData.push(element.item[temp]);
} else {
tempData.push("---");
}
final_obj[temp] = tempData;
len--;
}
});
console.log(final_obj);
//
category:["phone"]
name:["Product_1"],
price:[120],
qty:["---"],
You could do this with reduce() method that will return object and inside use forEach() loop.
const props = ["name", "price", "qty", "category"];
const obj = {"c1s6c156a1cascascas":{"item":{"name":"Product_1","price":120,"category":"phone"}},"c454asc5515as41cas78":{"item":{"name":"Product_2","price":7893,"category":"program_eq","qty":5}}}
const result = Object.values(obj).reduce((r, e) => {
props.forEach(prop => {
if(!r[prop]) r[prop] = []
r[prop].push(e.item[prop] || null)
})
return r;
}, {})
console.log(result)
This is how I would handle it:
const final_obj = { };
const props = ["name", "price", "qty", "category"];
const obj = {"c1s6c156a1cascascas":{"item":{"name":"Product_1","price":120,"category":"phone"}},"c454asc5515as41cas78":{"item":{"name":"Product_2","price":7893,"category":"program_eq","qty":5}}}
// set up each property as an empty array in the object
props.forEach(item => {
final_obj[item] = [];
});
// this iterates over every property in the object
_.forOwn(obj, value => {
props.forEach(item => {
// just push the values undefined or no into each property array
final_obj[item].push(value.item[item]);
});
});
console.log(final_obj);
You can do as well using some lodash functions.
Transform the array of props into an object which keys are the values of props and which values are extracted from the object. If the property doesn't exist in the object, return null.
const getValFromObj = (obj, key) => _.map(obj, _.partial(_.get, _, key, null));
const setValInResult = (res, key) => _.set(res, key, getValFromObj(obj, 'item.' + key));
const groupByProps = (props, obj) => _.transform(props, setValInResult, {});
const props = ["name", "price", "qty", "category"];
const obj = {
"c1s6c156a1cascascas": {
"item": {
"name": "Product_1",
"price": 120,
"category": "phone"
}
},
"c454asc5515as41cas78": {
"item": {
"name": "Product_2",
"price": 7893,
"category": "program_eq",
"qty": 5
}
}
}
console.log(groupByProps(props, obj));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>