How can I merge these 2 objects into 1? - javascript

I have 2 objects:
var set1 = {
name: "2020-02-17T00:00:00",
series: [
{ key: "055", value: 1154.47},
{ key: "056", value: 4132.2},
{ key: "059", value: 1825.33}
]
}
var set2 = {
startdate: "2020-02-17T00:00:00",
series: [
{key: "005",value: 0},
{key: "055",value: 0},
{key: "056",value: 0},
{key: "059",value: 0},
{key: "042",value: 0},
{key: "M002",value: 0}
]
}
How can I push the values of set1 onto set2 without overwriting any of the keys with value 0 as such:
var set2 = {
startdate: "2020-02-17T00:00:00",
series: [
{key: "005", value: 0},
{key: "055", value: 1154.47},
{key: "056", value: 4132.2},
{key: "059", value: 1825.33},
{key: "042", value: 0},
{key: "M002", value: 0}
]
}
Relevant code, you can see here: https://jsfiddle.net/xLr8qoes/1/

set2.series = [ ...set2.series, ...set1.series ];
This will set set2 series to be
[
{
"key": "005",
"value": 0
},
{
"key": "055",
"value": 0
},
{
"key": "056",
"value": 0
},
{
"key": "059",
"value": 0
},
{
"key": "042",
"value": 0
},
{
"key": "M002",
"value": 0
},
{
"key": "055",
"value": 1154.47
},
{
"key": "056",
"value": 4132.2
},
{
"key": "059",
"value": 1825.33
},
{
"key": "055",
"value": 1154.47
},
{
"key": "056",
"value": 4132.2
},
{
"key": "059",
"value": 1825.33
}
]

you can do it in both way
Using spread operator:
let object3=[...object1,...object2]
Using Older javascript:
let returnedTarget = Object.assign({},object1, object2);

Managed to work out a way in the end!
set2.series.forEach(element => {
if (set1.series.filter(e => e.key == element.key).length >= 1){
element.value = set1.series.filter(e => e.key == element.key)[0].value;
}
else element.value = 0;
})
For each object in set2.series it filters set1.series on matching keys. Filter returns an array so if length of array is > 0, that key/value pair exists in set1.
set2 = {
"startdate": "2020-02-17T00:00:00",
"series": [
{key: "005", value: 0},
{key: "042", value: 0},
{key: "055", value: 1154.47},
{key: "056", value: 4132.2},
{key: "059", value: 1825.33},
{key: "M002", value: 0}
]
}
Is there a better/simpler way than this?

Related

Compose object from nested list

I have a generic json generated from an XML.
{
"contextInfoDTOList": [
{
"key": "context_info",
"list": [
{
"key": "composition",
"list": [
{
"key": "parts",
"list": [
{
"key": "part",
"list": [
{
"list": [
{
"key": "materials",
"list": [
{
"key": "material",
"list": [
{
"key": "material_value",
"value": "100"
},
{
"key": "material_name",
"value": "polyester"
}
]
}
]
},
{
"key": "part_name",
"value": "LINING"
}
]
},
{
"list": [
{
"key": "materials",
"list": [
{
"key": "material",
"list": [
{
"key": "material_value",
"value": "100"
},
{
"key": "material_name",
"value": "cow leather"
}
]
}
]
},
{
"key": "part_name",
"value": "OUTER SHELL"
}
]
}
]
}
]
}
]
},
{
"key": "explanation"
}
]
}
]
}
I need to extract the information to something like this:
COMPOSITION
Lining
100 % polyester
Outer Shell
100 % cow leather
I have tried a forEach approach, acceding to the keys (composition, parts, materials...), but it gets so dirty and I cannot get the materials list.
I'm considering about using a reduce to obtain an object, but I don't know how to pass an object and use recursivity through the nested list.
Desired object:
export class ContextInfo {
composition: Composition;
explanation: string;
}
export class Composition {
parts: Part[] = [];
}
export class Part {
partName: string;
materials: Material[] = [];
}
export class Material {
name: string;
value: number;
}
Any help would be appreciated. Thanks in advance!
Now it's your responsibility, to work with the data...
let contextInfoDTOList = [{ key: "context_info", list: [{ key: "composition", list: [{ key: "parts", list: [{ key: "part", list: [{ list: [{ key: "materials", list: [{ key: "material", list: [{ key: "material_value", value: "100" }, { key: "material_name", value: "polyester" }] }] }, { key: "part_name", value: "LINING" }] }, { list: [{ key: "materials", list: [{ key: "material", list: [{ key: "material_value", value: "100" }, { key: "material_name", value: "cow leather" }] }] }, { key: "part_name", value: "OUTER SHELL" }] }] }] }] }, { key: "explanation" }] }]
function* getAllKeyValue(list = [], path = []) {
for (let item of list)
if ("value" in item)
yield [item, path]
else
yield* getAllKeyValue(item.list, path.concat(item.key))
}
for (let [item, _path] of getAllKeyValue(contextInfoDTOList)) {
console.log(item);
// Todo: work with the data
}
That's a pretty ugly input format you have. But by continually filtering and finding nodes, we can build your output in a fairly reasonable manner:
const byKey = (target) => ({key}) => key == target
const extract = (res) => res .contextInfoDTOList .filter (byKey ('context_info')) .map (info => ({
explanation: info .list .find (byKey ('explanation')) .value,
composition: info .list .find (byKey ('composition')) .list .filter (byKey ('parts')) .map (parts => ({
parts: parts .list .filter (byKey ('part')) .flatMap (p => p.list .map (q => q.list)) .map (part => ({
partName: part .find (byKey ('part_name')) .value,
material: part .find (byKey ('materials')) .list .map (material => ({
name: material .list .find (byKey ('material_name')) .value,
value: material .list .find (byKey ('material_value')) .value
}))
}))
}))
}))
const res = {contextInfoDTOList: [{key: "context_info", list: [{key: "composition", list: [{key: "parts", list: [{key: "part", list: [{list: [{key: "materials", list: [{key: "material", list: [{key: "material_value", value: "100"}, {key: "material_name", value: "polyester"}]}]}, {key: "part_name", value: "LINING"}]}, {list: [{key: "materials", list: [{key: "material", list: [{key: "material_value", value: "100"}, {key: "material_name", value: "cow leather"}]}]}, {key: "part_name", value: "OUTER SHELL"}]}]}]}]}, {key: "explanation", value: "foobar"}]}]}
console .log (extract (res))
.as-console-wrapper {max-height: 100% !important; top: 0}
(Note that I had to add a dummy "value" to your "explanation" node to get it to extract properly. If we don't do this, we'd get an undefined explanation.)
We use the helper byKey simply to reduce the noise in the body of the function.

How to .map correctly this array of objects?

I'm not sure what I'm doing wrong but I would like to map an array of objects. This array of objects it's dynamic, this means sometimes it has 4 objects and sometimes 20, so I need to make sure it will work no matters how many entries it has:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
I need to pass this objects into one to send it through a POST call that should match this format:
form: {
'one': 'something',
'two': 'random',
'blue': 'chicken',
'orange': 'sportsman'
}
I can access to item.value but IDK why I can't item.key:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = obj.map(function combined(item) {
return {
item.key: item.value
};
})
console.log(combined);
Any ideas? Thanks.
You shouldn't return an object from your callback function. Return an array of the key and value, then use Object.fromEntries() to turn this into a single object with those keys and values.
var obj = [{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = Object.fromEntries(obj.map(item => [item.key, item.value]));
console.log(combined);
1) You can't use a map here because the map will return a new array. You can achieve this result using reduce
var obj = [
{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = obj.reduce((acc, curr) => {
const { key, value } = curr;
acc[key] = value;
return acc;
}, {});
console.log(result);
2) You can also do this using for..of loop
var obj = [{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = {};
for (let o of obj) {
result[o.key] = o.value;
}
console.log(result);

How to replace key/value pairs in an object of two arrays of objects

I would like to replace the key 'id' and it's value with the property of 'type' with a value of 'inc'or 'exp'. I also want to delete the property 'percentage' from the objects in the exp array.
In the end I want to merge al the objects into one array.
This is what I did, it has the desired outcome but there must be a shortcut to achieve this, with less code and cleaner. Thanks!
const list = {
exp: [
{ id: 0, value: 57, percentage: 12 },
{ id: 1, value: 34, percentage: 10 },
],
inc: [
{ id: 1, value: 18 },
{ id: 1, value: 89 },
],
};
// Deep copy of list object
let newList = JSON.parse(JSON.stringify(list));
// Destructuring
const { exp, inc } = newList;
for (let obj of exp) {
obj.type = "exp";
delete obj.id;
delete obj.percentage;
}
for (let obj2 of inc) {
obj2.type = "inc";
delete obj2.id;
}
//Spread operator
newList = [...newList.exp, ...newList.inc];
console.log(newList);
You could use flatMap in the support of Object.entries()
const list = {
exp: [
{ id: 0, value: 57, percentage: 12 },
{ id: 1, value: 34, percentage: 10 },
],
inc: [
{ id: 1, value: 18 },
{ id: 1, value: 89 },
],
};
const res = Object.entries(list).flatMap(([type, values]) =>
values.map((value) => ({
value: value.value,
type: type,
}))
);
console.log(res);
Step by step
A = Object.entries(list)
// -->
[
[
"exp",
[
{ "id": 0, "value": 57, "percentage": 12 },
{ "id": 1, "value": 34, "percentage": 10 }
]
],
[
"inc",
[
{ "id": 1, "value": 18 },
{ "id": 1, "value": 89 }
]
]
]
B = A.map(...)
// -->
[
[
{ "value": 57, "type": "exp" },
{ "value": 34, "type": "exp" }
],
[
{ "value": 18, "type": "inc" },
{ "value": 89, "type": "inc" }
]
]
C = B.flat()
// -->
[
{ "value": 57, "type": "exp" },
{ "value": 34, "type": "exp" },
{ "value": 18, "type": "inc" },
{ "value": 89, "type": "inc" }
]
flatMap is the combination of step B and C (.map then .flat)
If value is the only property you want:
const list = {
exp: [
{ id: 0, value: 57, percentage: 12 },
{ id: 1, value: 34, percentage: 10 }
],
inc: [
{ id: 1, value: 18 },
{ id: 1, value: 89 }
]
};
const newList = [];
const types = Object.keys(list);
types.forEach((type) => {
list[type].forEach(({ value }) => {
newList.push({ type, value });
});
});
console.log(newList);
console.log(JSON.stringify(newList));

Sorting an array of objects reference of other array of objects

I have two arrays of objects
const reference_array= [{"key":"oAuthAccessToken","label":"Access Token","value":""},{"key":"clientId","label":"Client ID","value":""},{"label":"Verification Token","key":"verificationToken","value":""},{"label":"User ID","key":"userId","value":""},{"key":"signingSecret","label":"Signing Secret","value":""},{"label":"App ID","key":"appId","value":""},{"label":"Team ID","key":"teamId","value":""},{"label":"Name","key":"name","value":""},{"label":"Client Secret","key":"clientSecret","value":""},{"label":"ID","key":"id","value":""},{"label":"Channel ID","key":"channelId","value":""},{"key":"","value":""}]
const resArray = [{"key":"3111","value":"12111"},{"key":"656556","value":"55666664"},{"key":"oAuthAccessToken","value":"123"},{"key":"clientId","value":"5"},{"key":"webhook_URL","value":"https://api.slack.com/1.1/account_activity/all/dev/webhooks.json?ref=7364616106833455"},{"key":"verificationToken","value":"55525"},{"key":"userId","value":"254"},{"key":"createdDate","value":"2019-09-05T07:47:24Z"},{"key":"createdBy","value":"John"},{"key":"webhook_ID","value":"7364616106833455"},{"key":"signingSecret","value":"12476233"},{"key":"appId","value":"9886"},{"key":"teamId","value":"8955653563"},{"key":"name","value":"56565"},{"key":"clientSecret","value":"656665656"},{"key":"id","value":"5656565"},{"key":"channelId","value":"55655565"}]
I would like to sort the resArray based on order of reference_array, the similar things of the two arrays is key value.
How to sort the resArray based on order of reference_array.
I tried in many ways but i have no luck.please help me to resolve the issue like below
Thanks in advance
resArray.sort(function(a, b) {
return reference_array.map(function(x) {return x.key; }).indexOf(b) - reference_array.map(function(x) {return x.key; }).indexOf(a);
});
Expected Output :
const resArray = [{
"key": "oAuthAccessToken",
"value": "123"
}, {
"key": "clientId",
"value": "5"
}, {
"key": "verificationToken",
"value": "55525"
}, {
"key": "userId",
"value": "254"
}, {
"key": "signingSecret",
"value": "12476233"
}, {
"key": "appId",
"value": "9886"
}, {
"key": "teamId",
"value": "8955653563"
}, {
"key": "name",
"value": "56565"
}, {
"key": "clientSecret",
"value": "656665656"
}, {
"key": "id",
"value": "5656565"
}, {
"key": "channelId",
"value": "55655565"
}, {
"key": "3111",
"value": "12111"
}, {
"key": "656556",
"value": "55666664"
}, {
"key": "webhook_URL",
"value": "https://api.slack.com/1.1/account_activity/all/dev/webhooks.json?ref=7364616106833455"
}, {
"key": "createdDate",
"value": "2019-09-05T07:47:24Z"
}, {
"key": "createdBy",
"value": "John"
},
{
"key": "webhook_ID",
"value": "7364616106833455"
}
]
You could take an object as reference for the sorting order and take Infinity for unknown key for sorting this items to the bottom of the array.
var reference = [{ key: "oAuthAccessToken", label: "Access Token", value: "" }, { key: "clientId", label: "Client ID", value: "" }, { label: "Verification Token", key: "verificationToken", value: "" }, { label: "User ID", key: "userId", value: "" }, { key: "signingSecret", label: "Signing Secret", value: "" }, { label: "App ID", key: "appId", value: "" }, { label: "Team ID", key: "teamId", value: "" }, { label: "Name", key: "name", value: "" }, { label: "Client Secret", key: "clientSecret", value: "" }, { label: "ID", key: "id", value: "" }, { label: "Channel ID", key: "channelId", value: "" }, { key: "", value: "" }],
array = [{ key: "3111", value: "12111" }, { key: "656556", value: "55666664" }, { key: "oAuthAccessToken", value: "123" }, { key: "clientId", value: "5" }, { key: "webhook_URL", value: "https://api.slack.com/1.1/account_activity/all/dev/webhooks.json?ref=7364616106833455" }, { key: "verificationToken", value: "55525" }, { key: "userId", value: "254" }, { key: "createdDate", value: "2019-09-05T07:47:24Z" }, { key: "createdBy", value: "John" }, { key: "webhook_ID", value: "7364616106833455" }, { key: "signingSecret", value: "12476233" }, { key: "appId", value: "9886" }, { key: "teamId", value: "8955653563" }, { key: "name", value: "56565" }, { key: "clientSecret", value: "656665656" }, { key: "id", value: "5656565" }, { key: "channelId", value: "55655565" }],
order = reference.reduce((o, { key }, i) => (o[key] = i + 1, o), {});
array.sort((a, b) => (order[a.key] || Infinity) - (order[b.key] || Infinity));
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

sorting object by keys (strings as numbers)

I have this data set in object, keys are strings
{ '17': '17-17:30',
'20': '20:00-21',
'21': '21-22',
'22': '22-23',
'23': '23-24',
'01': '1-2',
'02': '2-3',
'03': '3-4',
'04': '4-5',
'05': '5-6',
'06': '6-7',
'07': '7-7:30',
'08': '08:50-9' }
I want to arrange them numerically so that 01 comes first and 23 comes last.
Here's the code I'm using:
var sort_object = function(map) {
var keys = _.sortBy(_.keys(map), function(a) { return Number(a); });
var newmap = {};
_.each(keys, function(k) {
newmap[k] = map[k];
});
return newmap;
}
it still returns 17 in the beginning.
Where did I go wrong?
As Blender pointed out, objects are not ordered. You need to use an array. There are several ways you could set up this array, and once you have the data in an array it's very easy to sort it.
Here are a couple of examples. First, let's try making this an array of arrays. The outer array is the list of elements, and each element of this array is itself an array of two elements, your key and your value.
So paste this code into your favorite JavaScript console, such as the one in Chrome:
var data = [
[ '17', '17-17:30' ],
[ '20', '20:00-21' ],
[ '21', '21-22' ],
[ '22', '22-23' ],
[ '23', '23-24' ],
[ '01', '1-2' ],
[ '02', '2-3' ],
[ '03', '3-4' ],
[ '04', '4-5' ],
[ '05', '5-6' ],
[ '06', '6-7' ],
[ '07', '7-7:30' ],
[ '08', '08:50-9' ]
];
var result = data.slice().sort( function( a, b ) {
return +a[0] - +b[0];
});
JSON.stringify( result, null, 4 );
It will log:
[
[
"01",
"1-2"
],
[
"02",
"2-3"
],
[
"03",
"3-4"
],
[
"04",
"4-5"
],
[
"05",
"5-6"
],
[
"06",
"6-7"
],
[
"07",
"7-7:30"
],
[
"08",
"08:50-9"
],
[
"17",
"17-17:30"
],
[
"20",
"20:00-21"
],
[
"21",
"21-22"
],
[
"22",
"22-23"
],
[
"23",
"23-24"
]
Or, instead of an array of arrays, you can use an array of objects. This is often more convenient to work with. Paste this code into the JavaScript console:
var data = [
{ key: '17', value: '17-17:30' },
{ key: '20', value: '20:00-21' },
{ key: '21', value: '21-22' },
{ key: '22', value: '22-23' },
{ key: '23', value: '23-24' },
{ key: '01', value: '1-2' },
{ key: '02', value: '2-3' },
{ key: '03', value: '3-4' },
{ key: '04', value: '4-5' },
{ key: '05', value: '5-6' },
{ key: '06', value: '6-7' },
{ key: '07', value: '7-7:30' },
{ key: '08', value: '08:50-9'}
];
var result = data.slice().sort( function( a, b ) {
return +a.key - +b.key;
});
JSON.stringify( result, null, 4 );
It will log:
[
{
"key": "01",
"value": "1-2"
},
{
"key": "02",
"value": "2-3"
},
{
"key": "03",
"value": "3-4"
},
{
"key": "04",
"value": "4-5"
},
{
"key": "05",
"value": "5-6"
},
{
"key": "06",
"value": "6-7"
},
{
"key": "07",
"value": "7-7:30"
},
{
"key": "08",
"value": "08:50-9"
},
{
"key": "17",
"value": "17-17:30"
},
{
"key": "20",
"value": "20:00-21"
},
{
"key": "21",
"value": "21-22"
},
{
"key": "22",
"value": "22-23"
},
{
"key": "23",
"value": "23-24"
}
]
Either way, as you can see, once you have your data in a suitable format (i.e. the data as a whole needs to be an array), then it becomes very simple to sort it.
Let's look at that sort function in more detail (using the second example):
var result = data.slice().sort( function( a, b ) {
return +a.key - +b.key;
});
In this code a.key gets the value for the key property of one of the array elements. The + in front of that converts the string to a number - much like using the Number function but a simpler way to do it. Similarly for +b.key. And then subtracting those two numbers gives the correct sort function return: a positive, negative, or zero value depending on whether a.key or b.key is the greater of the two or if they're equal.
The first example works similarly, just using +a[0] - +b[0] instead of +a.key - +b.key.
The .slice() call in each example makes a copy of the array. You could omit that if you want to sort the original array.
The only way to imply order would be to use an array. How about an array of key/value objects, eg
return Object.keys(map).sort().map(function(k) {
return {key: k, value: foo[k]}
});

Categories