Divide json array into json arrays based on a key - javascript

I have a json array like this:
[
{id:1, another_id:1},
{id:2, another_id:1},
{id:3, another_id:2}
]
Is it possible to divide this into json arrays based on the key another_id. In this case two json arrays should be created like this
jsonArr1 = [
{id:1, another_id:1},
{id:2, another_id:1}
]
jsonArr2 = [
{id:3, another_id:2}
]
another_id will be varying. Please help guys

If you do not know how many different result arrays you will have, you should not try to make a variable for each of them. Instead put them in an object, where each object property corresponds to a single possible value of another_id, and the value for it is the corresponding array.
You can achieve that with reduce:
var data = [{id:1, another_id:1},{id:2, another_id:1},{id:3, another_id:2}];
var result = data.reduce( (acc, obj) => {
acc[obj.another_id] = acc[obj.another_id] || [];
acc[obj.another_id].push(obj);
return acc;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If you want different variables then you can build a function which will return filtered array based on the passed value. This will use Array.filter()
function formatData(check) {
var data = [{
id: 1,
another_id: 1
},
{
id: 2,
another_id: 1
},
{
id: 3,
another_id: 2
}
];
return data.filter(el => el.another_id === check);
}
jsonArr1 = formatData(1);
jsonArr2 = formatData(2);
console.log(jsonArr1);
console.log(jsonArr2);

I hope the code below will work for you. As this will create two separate json arrays Arr1 for id and Arr2 for another_id
data = [
{id:1, another_id:1},
{id:2, another_id:1},
{id:3, another_id:2}
];
console.log(data);
var Arr1 = [];
var Arr2 = [];
for(var i in data){
Arr1.push(data[i].id);
Arr2.push(data[i].another_id);
}

Related

Move object to the subset if the key is matched

[{id:1, name:'Chan', supervisor:''},
{id:2, name:'Wong', supervisor:'1'},
{id:3, name:'Fong', supervisor:'1'},
{id:4, name:'Ho', supervisor:'2'},
]
expected result
[
{
id: 1,
name: "Chan",
supervisor: "",
children: [
{
id: 2,
name: "Wong",
supervisor: "1",
children: [{ id: 4, name: "Ho", supervisor: "2" }]
},
{ id: 3, name: "Fong", supervisor: "1" }
]
}
]
I want to achieve this format like the above. Have tried to use lodash map and filter.
Want to know if there any fastest method to do that? Many thanks in advance.
Currently I have tried.
let children = [];
const transformedDataRecords = records.map((record) => {
let user = _.filter(records, { id: record.supervisor });
if (user.length>0) {
console.log(user[0].children);
if(!!(user[0].children)){
children = user[0].children;
}
children.push(record);
user = { ...user, children };
console.log(user);
}
});
Starting from
const staff = [{id:1, name:'Chan', supervisor:''},
{id:2, name:'Wong', supervisor:'1'},
{id:3, name:'Fong', supervisor:'1'},
{id:4, name:'Ho', supervisor:'2'},
]
This is a nice place to use Maps. You can keep a reference to each object by its ID without having to care about its location in the array:
const staffById = new Map(
// key-value pairs
staff.map(person => [person.id, person])
)
// Create the children arrays
staff.forEach(
person => {
if (person.supervisor !== "") {
// Maps do care about whether data is String or Number so we have to
// convert the supervisor field to Number to ensure they match.
const supervisorParsed = Number(person.supervisor)
const supervisorObj = staffById.get(supervisorParsed)
// Ensure there is an array to insert into
supervisorObj.children = supervisorObj.children || []
supervisorObj.children.push(person)
}
}
)
// References updated, now filter out everyone from the top-level array who is not a top-level supervisor.
const output = staff.filter(person => person.supervisor === '')

How to get objects with a common property from an array in lodash?

Hello there good Samaritan, i would like to use Lodash and find the user with most books in the array.
const books = [ {id:0, name: 'Adam', title: 'xx'}, {id:1, name:'Jack', title:'yy'}, { id: 2, name: 'Adam',title:'zz' } ]
Thanks in advance :)
function search_book(nameKey, myArray){
for (var i=0; i < myArray.length; i++) {
if (myArray[i].book === nameKey) {
return myArray[i];
}
}
}
var array = [
{ book:"deep learning", value:"this", other: "that" },
{ book:"ml", value:"this", other: "that" }
];
var resultObject = search_book("ml", array);
console.log(resultObject)
_.filter(list, { name: 'Adam' })
var group = _.countBy(list, function(item){return item.name});
That will get the counts of author in the list, then you can sort and find the one with the largest.
You can generate a function with lodash's _.flow():
Count the objects by the name property
Convert the resulting object of the previous step to [key, value] pairs,
Find the pair with the max value
Get the key (the name)
const { flow, countBy, toPairs, maxBy, tail, head } = _
const fn = flow(
arr => countBy(arr, 'name'), // count by name
toPairs, // convert to [key, value] pairs
arr => maxBy(arr, tail), // find the max by the value (tail)
head // get the key (head)
)
const books = [ {id:0, name: 'Adam', title: 'xx'}, {id:1, name:'Jack', title:'yy'}, { id: 2, name: 'Adam',title:'zz' } ]
const result = fn(books)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
And the same idea using Lodash/fp:
const { flow, countBy, toPairs, maxBy, tail, head } = _
const fn = flow(
countBy('name'), // count by name
toPairs, // convert to [key, value] pairs
maxBy(tail), // find the max by the value (tail)
head // get the key (head)
)
const books = [ {id:0, name: 'Adam', title: 'xx'}, {id:1, name:'Jack', title:'yy'}, { id: 2, name: 'Adam',title:'zz' } ]
const result = fn(books)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash#4(lodash.min.js+lodash.fp.min.js)'></script>

Loop Over Array of Objects and Combine them if they have similar keys

I am trying to iterate over an array that's similar to the below structure, and for each object that has the same id, I want them combined into a single object but with an array of all the 'names' associated with that id. My Array is pre-sorted by id and I can't use JQuery, only vanilla JS.
Convert this:
var array = [
{id=1, name = "Orange"},
{id=1, name = "Blue"},
{id=1, name = "Green"},
{id=2, name = "Blue"},
{id=3, name = "Orange"},
{id=3, name = "Blue"}
]
To this:
var newArray = [
{id=1, nameList = [Orange, Blue, Green]},
{id=2, nameList = [Blue]},
{id=3, namelist = [Orange, Blue]}
]
I was trying to do something like this by comparing the first object to the next object in the array, then setting the first object to the second object, but got stuck because 'secondObject' wasn't actually the next object in the array.
for (var i in array) {
firstObject = array[i];
secondObject = array[i + 1];
if (firstObject.id === secondObject.id) {
firstObject['nameList'] = [firstObject.name + ',' + secondObject.name]
} else {
continue;
}
firstObject = secondObject;
}
I have to do this with a couple thousand id's, and most of the id's are repeated with different names, but there are a few single id objects like id 2.
An alternative is using the function reduce
var array = [ {id:1, name : "Orange"}, {id:1, name : "Blue"}, {id:1, name : "Green"}, {id:2, name : "Blue"}, {id:3, name : "Orange"}, {id:3, name : "Blue"}]
var result = Object.values(array.reduce((a, c) => {
(a[c.id] || (a[c.id] = {id: c.id, nameList: []})).nameList.push(c.name);
return a;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Because of the sorted items, you could check the last item in the result array and if different from the actual item generate a new result object. Later push name.
var array = [{ id: 1, name: "Orange" }, { id: 1, name: "Blue" }, { id: 1, name: "Green" }, { id: 2, name: "Blue" }, { id: 3, name: "Orange" }, { id: 3, name: "Blue" }],
grouped = array.reduce(function (r, { id, name }) {
if (!r.length || r[r.length - 1].id !== id) {
r.push({ id, namelist: [] });
}
r[r.length - 1].namelist.push(name);
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you don't have to do it in-place, you can just create another object and put things into that directly.
var map = {}
for (var obj in array) {
var id = obj.id;
var name = obj.name;
if (!map[id]) {
map[id] = [];
}
map[id].push(name);
}
Then iterate across the map to build up your result:
var result = [];
Object.keys(map).forEach(function(key) {
result.push[key, map[key]];
}

es6 merge two array of objects and override the existing object

I have 2 array of objects:
const arr1 = [{'id':'1' 'value':'yes'}, {'id':'2', 'value':'no'}];
const arr2 = [{'id':'2', 'value':'yes'}];
So, if I try and merge these 2 arrays the result should be:
arrTemp = [{'id':'1', 'value':'yes'}, {'id':'2', 'value':'yes'}];
Basically, it should work similar to Object.assign(), but no matter what I try it does not work. Could anyone please help me in this ?
I modified the data structure. Is it possible to merge them now and get the output.
Thanks
This is how you can get the job done with ES6 spread, reduce and Object.values.
const arr1 = [{
'id': '1',
'value': 'yes'
}, {
'id': '2',
'value': 'no'
}];
const arr2 = [{
'id': '2',
'value': 'yes'
}];
const result = Object.values([...arr1, ...arr2].reduce((result, {
id,
...rest
}) => {
result[id] = {
...(result[id] || {}),
id,
...rest
};
return result;
}, {}));
console.log(result);
const result = Object.entries(Object.assign({}, ...arr1,...arr2)).map(([key, value]) => ({[key]:value}));
You could spread (...) the arrays into one resulting object ( via Object.assign) and then map its entries to an array again.
You could work with a valid ES6 data structure like a map for example:
const 1 = { 1: { string: 'yes' }, 2: { string: 'no' } }
const 2 = { 2: { string: 'yes' }, 3: { string: 'no' } }
const 3 = { ...1, ...2}
This will override your first argument with the second one or just combine them where possible.
Just try it out in your browser it's a lot easier and enhances performance since you will never have to use findById() which is an expensive operation.
In javascript, arrays are simply objects indexed by numbers starting from 0.
So when you use Object.assign on arr1 and arr2 you will override the first item in the arr1 with the first item in arr2 because they are both indexed under the key 0.
your result will be:
[
{ '2': 'yes' },
{ '2': 'no' }
]
(or in object syntax:)
{
0: { '2': 'yes' },
1: { '2': 'no' }
}
Instead of using arrays, you could create an object indexed by the number string (which is how you seem to be thinking of the array in any case).
So you could change your original data structure to make the job easier:
const arr1 = {
'1': 'yes',
'2': 'no'
};
const arr2 = {
'2': 'yes'
};
const result = Object.assign(arr1, arr2);
You could take a Map as reference to the new assigned object in the result array and build first a new array with a copy of the objects and then iterate the second array and update the objects with the same key.
var array1 = [{ 1: 'yes' }, { 2: 'no' }],
array2 = [{ 2: 'yes' }],
getKey = o => Object.keys(o)[0],
map = new Map,
result = array1.map(o => (k => map.set(k, Object.assign({}, o)).get(k))(getKey(o)));
array2.forEach(o => Object.assign(map.get(getKey(o)), o));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Array reduce could come in handy is this case. See example below:
[...arr1, ...arr2].reduce((acc, item) => {
const updated = acc.find(a => a.id === item.id)
if (!updated) {
acc.push(item)
} else {
const index = acc.indexOf(updated)
acc[index] = { ...item, ...acc[index] }
}
return acc
}, [])
simple way to add with exist array of object:
const arr1 = [{ "name":"John", "age":30, "car":"toyata" }];
const arr2 = [{ "name":"Ales", "age":40, "car":"Nissan" }];
Array.prototype.push.apply(arr1, arr2);
Result:=>
console.log(arr1)
For anyone finding this answer at a later point in time. There are a couple of ways that you could want this to work exactly, but you could filter all adjusted elements in the first array, and then combine it with the second array.
const arr3 = [...arr1.filter(item1 => !arr2.find(item2 => item1.id === item2.id)), ...arr2]
Alternatively, you could update the elements in the first array, and then filter them from the second array instead.
You cannot use array.prototype map because the key of arr1 and arr2 have the same value '2'.
You should use something like this
for (var i = 0, l = arr1.length; i < l; i++) {
var key = Object.keys(arr1[i]);
if (!arr2[key]) { arr2[key] = []; }
arr2[key].push(arr1[i][key]);
}
Regards

Reorder a provided JSON to a Specified Format

I need an optimized way to reorder the following JSON in JavaScript:
[
{"Values":["2005","Australia","$304749.10"]},
{"Values":["2005","France","$143130.80"]},
{"Values":["2006","Australia","$651979.82"]},
{"Values":["2006","France","$332496.01"]},
]
into this format:
[
{"Values":["Australia","2005","$304749.10"]},
{"Values":["Australia","2006","$651979.82"]},
{"Values":["France","2005","$143130.80"]},
{"Values":["France","2006","$332496.01"]},
]
var data=[
{"Values":["2005","Australia","$304749.10"]},
{"Values":["2005","France","$143130.80"]},
{"Values":["2006","Australia","$651979.82"]},
{"Values":["2006","France","$332496.01"]},
]
May reorder the props first:
data=data.map(({Values:[year,location,price]})=>({Values:[location,year,price}]));
Then sort alphabetically after the first prop:
data.sort(({Values:[loca]},{Values:[locb]})=>loca.localeCompare(locb));
http://jsbin.com/yekiropozu/edit?console
Note that this uses ES6 object destructuring...
You could first swap the first two items of the inner array and then sort the whole array by country and then by year.
var array = [{ Values: ["2005", "Australia", "$304749.10"] }, { Values: ["2005", "France", "$143130.80"] }, { Values: ["2006", "Australia", "$651979.82"] }, { Values: ["2006", "France", "$332496.01"] }];
array.forEach(a => [a.Values[0], a.Values[1]] = [a.Values[1], a.Values[0]]);
array.sort((a, b) => a.Values[0].localeCompare(b.Values[0]) || a.Values[1] - b.Values[1]);
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script>
var data = [
{"Values":["2005","Australia","$304749.10"]},
{"Values":["2005","France","$143130.80"]},
{"Values":["2006","Australia","$651979.82"]},
{"Values":["2006","France","$332496.01"]},
];
var data2 = data;
for(i=0;i<data.length;i++){
data2[i].Values[1] = data[i].Values[0];
data2[i].Values[0] = data[i].Values[1];
}
console.log(data2);
</script>

Categories