How can I add name to existing value pair in json - javascript

Hello this is my sample json:
{
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
}
Now I want something like
[
{"Month":"2016-01-01T00:00:00Z", "Number": 1},
{"Month":"2016-02-01T00:00:00Z", "Number": 2},
{"Month":"2016-03-01T00:00:00Z", "Number": 3}
]
How can I do this using JS/Jquery? I wanted to change it to the above mentioned format because I need to put them in html table and I found out that using the second format makes my job easier.

you can do this in the following way
let obj = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
let result = [];
for(element in obj){
result.push({"Month":element, "Number": obj[element]})
}
console.log(result);

You can use the jQuery map function to change the format of an array.
let jsonArray = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
var result = $.map(jsonArray, function (item, key) {
return {
Month: key,
Number: item
};
});

You could take the keys with Object.keys and use Array#map for mapping the new objects.
var object = { "2016-01-01T00:00:00Z": 1, "2016-02-01T00:00:00Z": 2, "2016-03-01T00:00:00Z": 3 },
result = Object.keys(object).map(function (k) {
return { Month: k, Number: object[k] };
});
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

var object1 = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
};
var finalArray = [];
for (var key in object1) {
if (p.hasOwnProperty(key)) { // p.hasOwnProperty this will check for duplicate key
finalArray.push({
“Month” : key,
“Number”:p[key]
});
}
}
console.log(finalArray)

Another option could include using Object.keys along with map as such...
let obj = {
'2016-01-01T00:00:00Z': 1,
'2016-02-01T00:00:00Z': 2,
'2016-03-01T00:00:00Z': 3
}
let arr = Object.keys(obj).map(key => {
return {'Month': key, 'Number': obj[key]}
});
JSFiddle demo

use $.each for travelling
a = {
"2016-01-01T00:00:00Z": 1,
"2016-02-01T00:00:00Z": 2,
"2016-03-01T00:00:00Z": 3
}
var b = [];
$.each( a, function( key, value ) {
b.push({mounth: key ,number: value });
});
Output will be:
0:{mounth: "2016-01-01T00:00:00Z", number: 1}
1:{mounth: "2016-02-01T00:00:00Z", number: 2}
2:{mounth: "2016-03-01T00:00:00Z", number: 3}

Related

Get specific data from array and put in other array

I have this result in javascript and i want to get data that has value more that 3 and i want to put in other array .
"availableDates": {
"2020-01-24": 1,
"2020-01-23": 3,
"2020-01-22": 2,
"2020-01-21": 1,
"2020-01-25": 4,
"2021-01-07": 1
}
I group here :
const formattedDate = x.reduce((acc,el) => {
const date = el.split(" ")[0];
acc[date] = (acc[date] || 0) + 1;
return acc;
}, {});
now I want to put in other array all that date that has value more than 3 . For example
newarray = [ "2020-01-23", "2020-01-25" ]
Why don't use a simple .filter() over keys of "availableDates":
const grouped = {
"availableDates": {
"2020-01-24": 1,
"2020-01-23": 3,
"2020-01-22": 2,
"2020-01-21": 1,
"2020-01-25": 4,
"2021-01-07": 1
}
};
const newArray = Object.keys(grouped.availableDates).filter((key) => grouped.availableDates[key] >= 3);
console.log(newArray);
You can simply use a for...in loop to iterate over object keys and filter them:
const data = {
"2020-01-24": 1,
"2020-01-23": 3,
"2020-01-22": 2,
"2020-01-21": 1,
"2020-01-25": 4,
"2021-01-07": 1
};
const reducer = (obj, val) => {
const result = [];
for(key in obj) {
if(obj[key] >= val)
result.push(key);
};
return result;
};
console.log(reducer(data, 3));
You could have something like this. I write a complete bunch of the code to make you able to copy/past to test
var availableDates = new Array()
var availableDates = {
"2020-01-24": 1,
"2020-01-23": 3,
"2020-01-22": 2,
"2020-01-21": 1,
"2020-01-25": 4,
"2021-01-07": 1
}
var results = new Array();
for (date in availableDates){
if (availableDates[date] >= 3){
results.push(date)
}
}
console.log(results)

Rearrange dynamic Object to form a structured Object

I have an Object like this:
const val = {"abc":{"1":1, "2":6,"3":5},"def":{"1":3, "2":4,"3":8},"xyz":{"1":5, "2":6,"3":7}}
I want to transform the object data like below:
[{"abc":1,"def":3,"xyz":5},{"abc":6,"def":4,"xyz":6}, ...]
All the values are dynamic, any number of inner object may be there
I have tried like this:
const val = {"abc":{"1":1, "2":6,"3":5},"def":{"1":3, "2":4,"3":8},"xyz":{"1":5, "2":6,"3":7}}
let dataObj = {};
let secondArr = [];
let dataArr =[]
Object.entries(val).map(firstObj=>{
Object.entries(firstObj[1]).forEach(secondObj => {
dataObj={[firstObj[0]]:secondObj[1]};
secondArr.push(dataObj);
})
dataArr.push(secondArr)
})
console.log(dataArr)
Can anyone tell me a solution for this?
Thanks in advance
You could iterate the entries of the objects and take the inner keys as indices of the array with new objects with outer key and value.
var data = { abc: { 1: 1, 2: 6, 3: 5 }, def: { 1: 3, 2: 4, 3: 8 }, xyz: { 1: 5, 2: 6, 3: 7 } },
result = Object
.entries(data)
.reduce((r, [k, o]) => {
Object.entries(o).forEach(([i, v]) =>
Object.assign(r[i - 1] = r[i - 1] || {}, { [k]: v }));
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

javascript merge array of objects, resulting object values in array

Would like to merge an array of objects resulting in an object of unique keys and array of values (duplication of values is ok). Solutions in vanilla JS or lodash preferred.
eg - from this:
[{
a: 1,
b: 2
}, {
a: 1,
c: 3
}]
to this:
{
a: [1, 1],
b: [2],
c: [3]
}
You can use _.mergeWith() with the spread syntax to combine the objects:
const data = [{"a":1,"b":2},{"a":1,"c":3}];
const result = _.mergeWith({}, ...data, (v1 = [], v2) => [...v1, v2]);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
ES6 variant:
const a = [{
a: 1,
b: 2
}, {
a: 1,
c: 3
}]
const b = a.reduce((acc, cur) => Object.assign(acc,
...Object.keys(cur).map(key => ({ [key]: (acc[key] || []).concat(cur[key]) })))
, {})
console.log(b)
without loadash:
var t = [{
a: 1,
b: 2
}, {
a: 1,
c: 3
}];
var result = {};
debugger;
for(var i=0; i<t.length; i++){
for(var j in t[i]){
if(result.hasOwnProperty(j)){
result[j].push(t[i][j]);
}else{
result[j] = [t[i][j]];
}
}
}
console.log(result);
A quick search here in stack reveals that #elclanrs already wrote code for that here However based on the comments, it needs a little tweaking to accept an array of objects, so I added a bit of change to the original code itself.
so basically it boils to the function call:
var merge = function() {
return [].reduce.call(arguments, function(acc, x) {
for(i=0;i<x.length;i++){
Object.keys(x[i]).forEach(function(k) {
acc[k] = (acc[k]||[]).concat([x[i][k]])
});
}
return acc
},{})
}
}
Here's a snippet using the function call (with a bit of small change I put) in that post:
var x = [{a: 1, b: 2}, {a: 1,c: 3}]
var merge = function() {
return [].reduce.call(arguments, function(acc, x) {
for(i=0;i<x.length;i++){
Object.keys(x[i]).forEach(function(k) {
acc[k] = (acc[k]||[]).concat([x[i][k]])
});
}
return acc
},{})
}
y = merge(x);
alert(JSON.stringify(y));
You can use lodash#mergeWith wrapped in a lodash#spread to make lodash#mergeWith treat an array as a list of arguments. We use lodash#concat as a supporting function to concatenate an empty object (to avoid mutating the objects in the collection), the collection, and the customizer function that merges the entire collection. The customizer is composed using lodash#flow, wherein its first argument is lodash#concat that only accepts an arity of 2 using lodash#ary and the second argument uses lodash#compact -- It removes all undefined values in an array.
var result = _.spread(_.mergeWith)(
_.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);
var data = [{
"a": 1,
"b": 2
}, {
"a": 1,
"c": 3
}];
var result = _.spread(_.mergeWith)(
_.concat({}, data, _.flow(_.ary(_.concat, 2), _.compact))
);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

How to merge two dictionaries in javascript

I have two arrays of objects:
Array1:
var myArr1 = [];
myArr1["1"]={any:1,some:1};
myArr1["2"]={any:2,some:2};
myArr1["3"]={any:3,some:3};
Array2:
var myArr2 = [];
myArr2["1"]={other:1};
myArr2["2"]={other:2};
And I want them to be merged by their keys into a new Attribute, so the result will be:
[
{any:1,some:1,myNewAttribute:{other:1}},
{any:2,some:2,myNewAttribute:{other:2}},
{any:3,some:3,myNewAttribute:{other:3}}
]
I tried to achieve it with lodash's _.merge() but I failed miserably. _.merge only adds the second array after the first, but does not match their keys / ids.
You could map the second array to a new property and merge later.
With lodash
var data1 = [{ any: 1, some: 1 }, { any: 2, some: 2 }, { any: 3, some: 3 }],
data2 = [{ other: 1 }, { other: 2 }, { other: 3 }];
console.log(_.merge(data1, _.map(data2, x => ({ myNewAttribute: x }))));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
With ES6, without lodash
var data1 = [{ any: 1, some: 1 }, { any: 2, some: 2 }, { any: 3, some: 3 }],
data2 = [{ other: 1 }, { other: 2 }, { other: 3 }];
console.log(data1.map((a, i) => Object.assign({}, a, { myNewAttribute: data2[i] })));
You don't need lodash:
myArr1.map((e1, idx) => Object.assign({}, e1, {myNewAttribute: myArr2[idx]}))
You could get fancy and write a little function called map2, which takes two arrays, and invokes a callback with the two elements:
function map2(a1, a2, fn) {
return a1.map((elt, idx) => fn(elt, a2[idx]);
}
Now you can write the solution as
map2(myArr1, myArr2, (e1, e2) => Object.assign({}, e1, {myNewAttribute: e2}))
From the perspective of program design, what we are doing here is "separating concerns". The first concern is the abstract operation of looping over two arrays in parallel and doing something with each pair of elements. That is what is represented by map2. The second concern is the specific way you want to combine the elements. That is what is represented by the function we are passing to map2. This could be made clearer and somewhat self-documenting by writing it separately:
function combineObjects(e1, e2) {
return Object.assign({}, e1, {myNewAttribute: e2});
}
map2(myArr1, myArr2, combineObjects);
Of course, in the real world, you'd want to handle the case where the two arrays were of different length, pass an index to the callback as a third parameter for use if necessary, support a third thisArg-type parameter analogous to map, etc.
You can do like this:
var first = [{any:1,some:1},{any:2,some:2},{any:3,some:3}];
var second = [{other:1},{other:2},{other:3}];
for(var i = 0; i < first.length; i++){
if(first[i] && second[i]){
first[i]['mycustomitem'] = second[i];
}
}
console.log(first);
In order to prove, what I did comment 30 minutes ago -
How to merge two dictionaries in javascript -
there is a possible reduce approach ...
... firstly provided as lodash based example ...
var
myArr1 = [
{any: 1, some: 1},
{any: 2, some: 2},
{any: 3, some: 3}
],
myArr2 = [
{other: 1},
{other: 2}
],
mergedObjectList = _.reduce(myArr1, function (collector, item_1, idx) {
var
item_2 = collector[idx],
merger = _.assign({}, item_1, item_2);
// or whatever one wants to do to `merger` with `myNewAttribute`
collector[idx] = merger;
return collector;
}, _.clone(myArr2));
console.log("myArr1 : ", myArr1);
console.log("myArr2 : ", myArr2);
console.log("mergedObjectList : ", mergedObjectList);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
... and secondly as language core only based example ...
var
myArr1 = [
{any: 1, some: 1},
{any: 2, some: 2},
{any: 3, some: 3}
],
myArr2 = [
{other: 1},
{other: 2}
],
mergedObjectList = myArr1.reduce(function (collector, item_1, idx) {
var
item_2 = collector[idx],
merger = Object.assign({}, item_1, item_2);
// or whatever one wants to do to `merger` with `myNewAttribute`
collector[idx] = merger;
return collector;
}, Array.from(myArr2));
console.log("myArr1 : ", myArr1);
console.log("myArr2 : ", myArr2);
console.log("mergedObjectList : ", mergedObjectList);
Try this function:
function mergeDictionary(_dctn1,_dctn2)
{
var newDict = [];
for(var i in _dctn1)
{
newDict[i] = _dctn1[i];
}
for(var j in _dctn2)
{
if(newDict[j] == undefined)
{
newDict[j] = _dctn2[j];
}
else
{
for(var k in _dctn2[j])
{
newDict[j][k] = _dctn2[j][k];
}
}
}
return newDict;
}
var myArr1 = [];
myArr1["1"]={any:1,some:1};
myArr1["2"]={any:2,some:2};
myArr1["3"]={any:3,some:3};
var myArr2 = [];
myArr2["1"]={other:1};
myArr2["2"]={other:2};
console.log(mergeDictionary(myArr1, myArr2));

JavaScript merging objects by id [duplicate]

This question already has answers here:
Most efficient method to groupby on an array of objects
(58 answers)
How to merge two arrays in JavaScript and de-duplicate items
(89 answers)
Closed 7 months ago.
What's the correct way to merge two arrays in Javascript?
I've got two arrays (for example):
var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
I want to be able to end up with something like:
var a3 = [{ id : 1, name : "test", count : "1"},
{ id : 2, name : "test2", count : "2"}]
Where the two arrays are being joined based on the 'id' field and extra data is simply being added.
I tried to use _.union to do this, but it simply overwrites the values from the second array into the first one
Short ES6 solution
const a3 = a1.map(t1 => ({...t1, ...a2.find(t2 => t2.id === t1.id)}))
This should do the trick:
var mergedList = _.map(a1, function(item){
return _.extend(item, _.findWhere(a2, { id: item.id }));
});
This assumes that the id of the second object in a1 should be 2 rather than "2"
Assuming IDs are strings and the order does not matter, you can
Create a hash table.
Iterate both arrays and store the data in the hash table, indexed by the ID. If there already is some data with that ID, update it with Object.assign (ES6, can be polyfilled).
Get an array with the values of the hash map.
var hash = Object.create(null);
a1.concat(a2).forEach(function(obj) {
hash[obj.id] = Object.assign(hash[obj.id] || {}, obj);
});
var a3 = Object.keys(hash).map(function(key) {
return hash[key];
});
In ECMAScript6, if the IDs are not necessarily strings, you can use Map:
var hash = new Map();
a1.concat(a2).forEach(function(obj) {
hash.set(obj.id, Object.assign(hash.get(obj.id) || {}, obj))
});
var a3 = Array.from(hash.values());
ES6 simplifies this:
let merge = (obj1, obj2) => ({...obj1, ...obj2});
Note that repeated keys will be merged, and the value of the second object will prevail and the repeated value of the first object will be ignored.
Example:
let obj1 = {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj1Val"};
let obj2 = {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj2Val"};
merge(obj1, obj2)
// {id: 1, uniqueObj1Key: "uniqueKeyValueObj1", repeatedKey: "obj2Val", uniqueObj2Key: "uniqueKeyValueObj2"}
merge(obj2, obj1)
// {id: 1, uniqueObj2Key: "uniqueKeyValueObj2", repeatedKey: "obj1Val", uniqueObj1Key: "uniqueKeyValueObj1"}
Complete solution (with Lodash, not Underscore)
var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
var merge = (obj1, obj2) => ({...obj1, ...obj2});
_.zipWith(a1, a2, merge)
(2) [{…}, {…}]
0: {id: 1, name: "test", count: "1"}
1: {id: 2, name: "test2", count: "2"}
If you have an array of arrays to merge you can do it like this:
var arrayOfArraysToMerge = [a1, a2, a3, a4]; //a3 and a4 are arrays like a1 and a2 but with different properties and same IDs.
_.zipWith(...arrayOfArraysToMerge, merge)
(2) [{…}, {…}]
0: {id: 1, name: "test", count: "1", extra1: "val1", extra2: 1}
1: {id: 2, name: "test2", count: "2", extra1: "val2", extra2: 2}
reduce version.
var a3 = a1.concat(a2).reduce((acc, x) => {
acc[x.id] = Object.assign(acc[x.id] || {}, x);
return acc;
}, {});
_.values(a3);
I think it's common practice in functional language.
Already there are many great answers, I'll just add another one which is from a real problem I needed to solve yesterday.
I had an array of messages with user ids, and one array of users containing users' names and other details. This is how I managed to add user details to the messages.
var messages = [{userId: 2, content: "Salam"}, {userId: 5, content: "Hello"},{userId: 4, content: "Moi"}];
var users = [{id: 2, name: "Grace"}, {id: 4, name: "Janetta"},{id: 5, name: "Sara"}];
var messagesWithUserNames = messages.map((msg)=> {
var haveEqualId = (user) => user.id === msg.userId
var userWithEqualId= users.find(haveEqualId)
return Object.assign({}, msg, userWithEqualId)
})
console.log(messagesWithUserNames)
Vanilla JS solution
const a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
const a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
const merge = (arr1, arr2) => {
const temp = []
arr1.forEach(x => {
arr2.forEach(y => {
if (x.id === y.id) {
temp.push({ ...x, ...y })
}
})
})
return temp
}
console.log(merge(a1, a2))
The lodash implementaiton:
var merged = _.map(a1, function(item) {
return _.assign(item, _.find(a2, ['id', item.id]));
});
The result:
[
{
"id":1,
"name":"test",
"count":"1"
},
{
"id":2,
"name":"test2",
"count":"2"
}
]
Wanted to add this answer which is derived from #daisihi answer above. Main difference is that this uses the spread operator.
Also, at the end I remove the id because it was not desirable in the first place.
const a3 = [...a1, ...a2].reduce((acc, x) => {
acc[x.id] = {...acc[x.id] || {}, ...x};
return acc;
}, {});
This part was taken from another post. removing a property from a list of objects in an array
const newArray = Object.values(a3).map(({id, ...keepAttrs}) => keepAttrs);
Found other solutions failing for some cases, so writing a better one here
const a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
const a2 = [{ id : 3, count : "3"}, { id : 1, count : "1"}, {id : 2, count : "2"}]
const mergeHelper = new Map(a1.map(x => [x.id, x]));
for (const x of a2) {
if (mergeHelper.has(x.id)) {
const item = mergeHelper.get(x.id);
mergeHelper.set(x.id, {...item, ...x});
} else {
mergeHelper.set(x.id, x);
}
}
const mergedList = [...mergeHelper.values()];
// For sorted array
// const mergedSortedList = [...mergeHelper.values()].sort((a, b) => a.id - b.id);
console.log(mergedList)
Using js Map is way faster than other approaches, helps when array length is huge.
A working TypeScript version:
export default class Merge {
static byKey(a1: any[], a2: any[], key: string) {
const res = a1.concat(a2).reduce((acc, x) => {
acc[x[key]] = Object.assign(acc[x[key]] || {}, x);
return acc;
}, {});
return Object.entries(res).map(pair => {
const [, value] = pair;
return value;
});
}
}
test("Merge", async () => {
const a1 = [{ id: "1", value: "1" }, { id: "2", value: "2" }];
const a2 = [{ id: "2", value: "3" }];
expect(Merge.byKey(a1, a2, "id")).toStrictEqual([
{
id: "1",
value: "1"
},
{ id: "2", value: "3" }
]);
});
try this
var a1 = [{ id : 1, name : "test"}, { id : 2, name : "test2"}]
var a2 = [{ id : 1, count : "1"}, {id : 2, count : "2"}]
let arr3 = a1.map((item, i) => Object.assign({}, item, a2[i]));
console.log(arr3);
How about this?
const mergeArrayObjects = (arr1: any[], arr2: any[], mergeByKey: string): any[] => {
const updatedArr = [];
for (const obj of arr1) {
const arr1ValueInArr2 = arr2.find(
a => a[mergeByKey] === obj[mergeByKey],
);
if (arr1ValueInArr2) {
updatedArr.push(Object.assign(obj, arr1ValueInArr2));
} else {
updatedArr.push(obj);
}
}
const mergeByKeyValuesInArr1 = arr1.map(a => a[mergeByKey]);
const remainingObjInArr2 = arr2.filter(a => !mergeByKeyValuesInArr1.includes(a[mergeByKey]) )
return updatedArr.concat(remainingObjInArr2)
}
You can write a simple object merging function like this
function mergeObject(cake, icing) {
var icedCake = {}, ingredient;
for (ingredient in cake)
icedCake[ingredient] = cake[ingredient];
for (ingredient in icing)
icedCake[ingredient] = icing[ingredient];
return icedCake;
}
Next, you need to do use a double-loop to apply it to your data structre
var i, j, a3 = a1.slice();
for (i = 0; i < a2.length; ++i) // for each item in a2
for (j = 0; i < a3.length; ++i) // look at items in other array
if (a2[i]['id'] === a3[j]['id']) // if matching id
a3[j] = mergeObject(a3[j], a2[i]); // merge
You can also use mergeObject as a simple clone, too, by passing one parameter as an empty object.
const a3 = a1.map(it1 => {
it1.test = a2.find(it2 => it2.id === it1.id).test
return it1
})
If you have exactly the same number of items in both array with same ids you could do something like this.
const mergedArr = arr1.map((item, i) => {
if (item.ID === arr2[i].ID) {
return Object.assign({}, item, arr2[i]);
}
});
function mergeDiffs(Schedulearray1, Schedulearray2) {
var secondArrayIDs = Schedulearray2.map(x=> x.scheduleid);
return Schedulearray1.filter(x=> !secondArrayIDs.includes(x.scheduleid)).concat(Schedulearray2);
}
None of them worked for me. I wrote own:
const formatteddata=data.reduce((a1,a2)=>{
for (let t=0; t<a1.length; t++)
{var id1=a1[t].id
for (let tt=0; tt<a2.length; tt++)
{var id2=a2[tt].id
if(id1==date2)
{a1[t]={...a1[t],...a2[tt]}}
}
}
return a1
})
works with any amount of arrays of objects in arrays, with varying length and not always coinsciding dates

Categories

Resources