Transform an object with an array into an array [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have the following data structure:
const data = {
"firstName": "A",
"lastName": "B",
"address": [{
"country": "France",
"city": "Paris"
},
{
"country": "Italy",
"city": "Rome"
}
],
};
Using Ramda I would like to transforms it into:
const result = [
{
"firstName": "A",
"lastName": "B",
"address": {
"country": "France",
"city": "Paris"
},
},
{
"firstName": "A",
"lastName": "B",
"address": {
"country": "Italy",
"city": "Rome"
},
},
];

You can use a converge function to fork the prop address and then join it with the main object for each address in the list:
/**
* R.pick could be replaced with R.omit
* to let you black list properties:
* R.omit(['address']); https://ramdajs.com/docs/#omit
**/
const createByAddress = R.converge(R.map, [
R.pipe(R.pick(['firstName', 'lastName']), R.flip(R.assoc('address'))),
R.prop('address'),
]);
const data = {
"firstName": "A",
"lastName": "B",
"address": [{
"country": "France",
"city": "Paris"
},
{
"country": "Italy",
"city": "Rome"
}
],
};
console.log(createByAddress(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js" integrity="sha256-xB25ljGZ7K2VXnq087unEnoVhvTosWWtqXB4tAtZmHU=" crossorigin="anonymous"></script>

My question is why "with Ramda"? I'm a founder of Ramda and a big fan, but it's just a tool, and unless this is a learning exercise for Ramda, it doesn't seem like there is any need to use it for this problem.
I would do it like this, using modern JS techniques:
const transform = ({address, ...rest}) =>
address .map (a => ({...rest, address: a}))
const data = {firstName: "A", lastName: "B", address: [{country: "France", city: "Paris"}, {country: "Italy", city: "Rome"}]}
console .log (
transform (data)
)

I am not sure if this will help you but if you want to generate multiple objects based on adress maybe this helps
const obj = {
firstName: "a",
lastName: "b",
adresses: [{
country: "France",
city: "Paris"
}, {
country: "Italy",
city: "Rome"
}]
};
adressAmount = obj.adresses.length;
const adressObjects = [];
for (let i = 0; i < adressAmount; i++) {
const {
adresses,
...objWithoutAdresses
} = obj;
objWithoutAdresses.adress = obj.adresses[i];
adressObjects.push(objWithoutAdresses);
}
console.log(adressObjects);

I found this pretty simple and short.
const data = {
"firstName": "A",
"lastName": "B",
"address": [{
"country": "France",
"city": "Paris"
},
{
"country": "Italy",
"city": "Rome"
}
],
};
let requiredData = data.address.map(element=>{
return {...data,address:element}
})
console.log(requiredData);

1) Create an empty dictionary
2) for loop the array and store index of each array in the dictionary as value

You can iterate the address array and create object as required
let obj = {
"firstName": "A",
"lastName": "B",
"address": [{
"country": "France",
"city": "Paris"
},
{
"country": "Italy",
"city": "Rome"
}
]
}
let newData = obj.address.map(function(item) {
return {
firstName: obj.firstName,
lastName: obj.lastName,
address: {
country: item.country,
city: item.city
}
}
});
console.log(newData)

Related

Array of objects: Count occurrences of a unique property in JavaScript [duplicate]

This question already has answers here:
Javascript group a JSON object by two properties and count
(7 answers)
Group and count values in an array
(4 answers)
Closed 1 year ago.
Given a sample JSON array of objects, like this....
[
{
"firstName": "Bob",
"lastName": "Smith",
"city": "Preston",
"st": "Florida",
"age": 15
},
{
"firstName": "Tom",
"lastName": "Jones",
"city": "Springfield",
"st": "Illinois",
"age": 34
},
{
"firstName": "Mary",
"lastName": "Hart",
"city": "Miami",
"st": "Florida",
"age": 22
},
{
"firstName": "Jenny",
"lastName": "Dixon",
"city": "Palm City",
"st": "Florida",
"age": 26
}
]
What is the best way to get the number of occurrences based on the groupings of a particular property? So, let's say I want to produce a JSON object that has each unique state ("st") and the number of occurrences....
[
{
"st": "Illinois",
"count": 1
},
{
"st": "Florida",
"count": 3
}
]
I can do it manually using a for-let, looping through the array, tracking the values as I loop, etc. But I'm sure there's a more efficient way using ES6. Can you please help me out? Thanks.
You can use Array#reduce to keep a tally
let counts = json.reduce((b, a) => {
let index = b.findIndex(j => j.st === a.st);
if (index > -1) b[index].count++;
else b.push({st: a.st, count: 1});
return b;
}, [])
#UPDATE: As mentioned by #epascarello, there is a more efficient way to go about this, removing the findIndex loop and using Object.values
const results = Object.values(json.reduce((obj, item) => {
obj[item.st] = obj[item.st] || { st: item.st, count: 0 };
obj[item.st].count++;
return obj;}, {}))
let json = [{
"firstName": "Bob",
"lastName": "Smith",
"city": "Preston",
"st": "Florida",
"age": 15
},
{
"firstName": "Tom",
"lastName": "Jones",
"city": "Springfield",
"st": "Illinois",
"age": 34
},
{
"firstName": "Mary",
"lastName": "Hart",
"city": "Miami",
"st": "Florida",
"age": 22
},
{
"firstName": "Jenny",
"lastName": "Dixon",
"city": "Palm City",
"st": "Florida",
"age": 26
}
]
let counts = json.reduce((b, a) => {
let index = b.findIndex(j => j.st === a.st);
if (index > -1) b[index].count++;
else b.push({st: a.st, count: 1});
return b;
}, [])
console.log(counts)
const results = Object.values(json.reduce((obj, item) => {
obj[item.st] = obj[item.st] || { st: item.st, count: 0 };
obj[item.st].count++;
return obj;}, {}))
console.log(results)

How to sum values in array by specific object key?

I have an array of js objects which look like this:
var objArr = [
{"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
{"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
{"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
{"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
]
I wanna create a new array where the country is unique, but also the dates should be summed.
{"Country": "US", "2017-07-12": "3", "2017-07-13": "4"},
{"Country": "CN", "2017-07-12": "10", "2017-07-13": "14"}
^^^^ ^^^^ ^^^^
I have problems getting my head around it.
Do I have to filter first, reduce it somehow, remap it,... I've no idea to start?
Any help would be appreciated, thank you!
Use Array.reduce, check if an object with the current country exists, if it does, loop through the Object.keys to update the values, if not, push a new one :
EDIT : If you don't want City you can destructure it {City, ...curr}
var objArr = [
{ Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
{ Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
{ Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
{ Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];
var result = objArr.reduce((acc, {City, ...curr}) => {
const ndx = acc.findIndex(e => e.Country === curr.Country);
if (ndx > -1) {
const [country, ...keys] = Object.keys(curr);
keys.forEach(k => {
acc[ndx][k] = +acc[ndx][k] + +curr[k];
});
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(result);
Use one forEach for array and go over each object date keys using forEach and build the one res object with unique keys as Country and accumulated values.
Use Object.values of res to get the array from res object.
Update: Fix to make sure always one type for dates which is number.
var objArr = [
{ Country: "US", City: "MyCity1", "2017-07-12": "1", "2017-07-13": "2" },
{ Country: "US", City: "MyCity2", "2017-07-12": "2", "2017-07-13": "2" },
{ Country: "CN", City: "MyCity1", "2017-07-12": "5", "2017-07-13": "7" },
{ Country: "CN", City: "MyCity2", "2017-07-12": "5", "2017-07-13": "7" }
];
const update = data => {
const res = {};
data.forEach(({ Country, City, ...dates }) => {
const item = res[Country] || { Country };
Object.keys(dates).forEach(date => {
item[date] = (item[date] || 0) + Number(dates[date]);
});
res[Country] = { ...item };
});
return Object.values(res);
};
console.log(update(objArr));
You can use reduce() to create an object to group elements and then use Object.values
var objArr = [
{"Country": "US", "City": "MyCity1", "2017-07-12": "1", "2017-07-13": "2"},
{"Country": "US", "City": "MyCity2", "2017-07-12": "2", "2017-07-13": "2"},
{"Country": "CN", "City": "MyCity1", "2017-07-12": "5", "2017-07-13": "7"},
{"Country": "CN", "City": "MyCity2", "2017-07-12": "5", "2017-07-13": "7"}
]
let keys = ["2017-07-12", "2017-07-13"];
const res = Object.values(objArr.reduce((ac, a) => {
if(!ac[a.Country]){
ac[a.Country] = {Country: a.Country};
}
keys.forEach(k => {
ac[a.Country][k] = (ac[a.Country][k] || 0) + Number(a[k]);
})
return ac;
}, {}))
console.log(res)

Merge values in object, if other value in the said object is the same

For example, I have an array like this.
[{
"Country": "USA", "Nickname": "John"
}, {
"Country": "Japan", "Nickname": "Grace"
}, {
"Country": "Japan", "Nickname": "Mark"
}, {
"Country": "Japan", "Nickname": "Paul"
}, {
"Country": "China", "Nickname": "Sansa"
}, {
"Country": "USA", "Nickname": "Clint"
}, {
"Country": "China", "Nickname": "James"
}, {
"Country": "Japan", "Nickname": "Mary"
}]
I want my array to look like this..
[{
"Country": "USA", "Nickname": "John , Clint"
}, {
"Country": "Japan", "Nickname": "Grace , Mark , Paul , Mary"
}, {
"Country": "China", "Nickname": "Sansa, James"
}]
I want to merge the nicknames by their country. What should I do?
Here is an easy example done by object and array.
Next time you can totally try it yourself, dude.
var arr = [{
"Country": "USA", "Nickname": "John"
}, {
"Country": "Japan", "Nickname": "Grace"
}, {
"Country": "Japan", "Nickname": "Mark"
}, {
"Country": "Japan", "Nickname": "Paul"
}, {
"Country": "China", "Nickname": "Sansa"
}, {
"Country": "USA", "Nickname": "Clint"
}, {
"Country": "China", "Nickname": "James"
}, {
"Country": "Japan", "Nickname": "Mary"
}]
var obj = {};
var new_arr = [];
for(var i=0;i<arr.length;i++){
var d = arr[i];
if(!obj[d['Country']])
obj[d['Country']] = [];
obj[d['Country']].push(d['Nickname']);
}
for(var key in obj){
new_arr.push({
"Country": key,
"Nickname": obj[key].join(' , ')
})
}
console.log(new_arr);
let arr = [{"Country": "USA", "Nickname": "John"}, {"Country": "Japan", "Nickname": "Grace"}, {"Country": "Japan", "Nickname": "Mark"}, {"Country": "Japan", "Nickname": "Paul"}, {"Country": "China", "Nickname": "Sansa"}, {"Country": "USA", "Nickname": "Clint"}, {"Country": "China", "Nickname": "James"}, {"Country": "Japan", "Nickname": "Mary"}];
let answer = [];
arr.forEach(x=>{
if(!answer.some(y => y.Country === x.Country)){
answer.push(x);
}else{
let country = answer.find(y => y.Country === x.Country);
country.Nickname = country.Nickname.concat(`, ${x.Nickname}`);
}
});
console.log(answer)
Use some to check existence in another Array, if not exist, push the item to new array, if exist, grab it and append the nickname.
I faced the same issue a while a ago and this how did and you can achieve this by simply using this:
let result = [];
arr.forEach(function(obj) {
let id = obj.Country;
if(!this[id]) {
result.push(this[id] = obj);
} else {
this[id].Nickname += `, ${obj.Nickname}`;
}
}, Object.create(null));
console.log(result);
In the result you will get your desired result... and I have tested it...
Before posting the question you should try it yourself... Everyone will advice you the same... You are still new here I think but for the next time you should try first and then ask where you stuck...
You can use reduce to group the array into an object. Use Object.entries to convert the object into an array. Use map to format the array.
var arr = [{"Country":"USA","Nickname":"John"},{"Country":"Japan","Nickname":"Grace"},{"Country":"Japan","Nickname":"Mark"},{"Country":"Japan","Nickname":"Paul"},{"Country":"China","Nickname":"Sansa"},{"Country":"USA","Nickname":"Clint"},{"Country":"China","Nickname":"James"},{"Country":"Japan","Nickname":"Mary"}];
var result = Object.entries(arr.reduce((c, v) => {
c[v.Country] = c[v.Country] || [];
c[v.Country].push(v.Nickname);
return c;
}, {})).map(([k, v]) => ({"Country": k,"Nickname": v.join(' , ')}));
console.log(result);

Sort nested json complex array

I search how to sort by place.city this kind of object who have id's for keys. The need is to keep id's for first keys…
{
"123": {
"place": {
"city": "New York",
"country": "USA"
},
"person": {
"name": "Bob",
"age": 45
}
},
"456": {
"place": {
"city": "Chicago",
"country": "USA"
},
"person": {
"name": "Louis",
"age": 34
}
},
"789": {
"place": {
"city": "Dallas",
"country": "USA"
},
"person": {
"name": "Kevin",
"age": 27
}
}
}
I try some kind of function like this and the expected result is not here.
let result = _(myObject).map(function (value, key) {
return _.defaults({ name: key }, value)
}).sortBy('city').value()
You can't sort an object.. You can, however, convert your object to an array and sort that.
var data ={
"123" : {
"place": {
"city": "New York",
"country": "USA"
},
"person": {
"name": "Bob",
"age": 45
}
},
"456" : {
"place": {
"city": "Chicago",
"country": "USA"
},
"person": {
"name": "Louis",
"age": 34
}
},
"789" : {
"place": {
"city": "Dallas",
"country": "USA"
},
"person": {
"name": "Kevin",
"age": 27
}
}
};
var sortedByPlace = _.sortBy(Object.keys(data).map(k => ({id:k, ...data[k]})), (d)=> d.place.city)
console.log(sortedByPlace);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.5/lodash.min.js"></script>
It is not possible to sort an object, you need to make it a list.
import { map, flow } from 'lodash'
import { sortBy } from 'lodash/fp'
cities => flow(
map(places, (place, id) => { id, ...place }),
sortBy('city'),
)()
Your second question begs the question (mh...) if you want local sort. That would be
import { mapValues } from 'lodash'
import { sortBy } from 'lodash/fp'
data => mapValues(data, sortBy('place.city'))
You cant sort an object. However you could create a sorted array that contains references to the objects:
const sorted = Object.values(myObject).sort((a, b) => a.place.city.localeCompare(b.place.city));
If you look at this answer, the following should work
var sort = function (prop, arr) {
prop = prop.split('.');
var len = prop.length;
arr.sort(function (a, b) {
var i = 0;
while( i < len ) { a = a[prop[i]]; b = b[prop[i]]; i++; }
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
});
return arr;
};
sort("place.city", myObject);
I realize the object I have to treat (get from an obscur API) is a little bit more complicated than my first example :/
So the responses you nicely give are not working anymore…
Do you see the subtlety on this new object ?
The point stay to sort by place.city
{
"123": {
0: {
"place": {
"city": "New York",
"country": "USA"
},
"person": {
"name": "Bob",
"age": 45
}
},
1: {
"place": {
"city": "New York",
"country": "USA"
},
"person": {
"name": "James",
"age": 32
}
}
},
"456": {
0: {
"place": {
"city": "Chicago",
"country": "USA"
},
"person": {
"name": "Louis",
"age": 34
}
},
1: {
"place": {
"city": "Chicago",
"country": "USA"
},
"person": {
"name": "Christine",
"age": 65
}
}
},
"789": {
0: {
"place": {
"city": "Dallas",
"country": "USA"
},
"person": {
"name": "Kevin",
"age": 27
}
},
1: {
"place": {
"city": "Dallas",
"country": "USA"
},
"person": {
"name": "Robert",
"age": 55
}
},
2: {
"place": {
"city": "Dallas",
"country": "USA"
},
"person": {
"name": "Danny",
"age": 62
}
}
}
}

filtering array based on key and value

I have an array in the below format which I need to filter based on the key and value. I am planning to use Underscore.js for this. I tried using the following code but it searches for all the fields value but I need to search based on the key and value and not in all the keys. How to use Underscore for this?
Please let me know.
var sortedArray = _.sortBy(_.filter(arr, function (obj) {
return _.values(obj).some(function (el) {
return (typeof el ==="string" && el.match(new RegExp(searchStr, "i")));
});
}), function (obj){
return obj[colName];
});
}
{
"recordsTotal": 5,
"recordsFiltered": 5,
"aaData": [
{
"firstname": "Pradeep",
"lastname": "Kumar",
"city": "Bangalore",
"country": "India"
},
{
"firstname": "John",
"lastname": "Wells",
"city": "Calcutta",
"country": "India"
},
{
"firstname": "Praveen",
"lastname": "Garg",
"city": "columbo",
"country": "Srilanka"
},
{
"firstname": "Joe",
"lastname": "Wells",
"city": "Luton",
"country": "UK"
},
{
"firstname": "Rita",
"lastname": "Wahlin",
"city": "houston",
"country": "USA"
}
]
}
Sorry if I was not able to post the question properly. I found a solution and the is using the below code.
var searchColData=function(arr, searchStr, colName){
var sortedArray = _.filter(arr, function (obj) {
return (_.property(colName)(obj).toString().match(new RegExp(searchStr, "i")));
});
return sortedArray;
}
Hope this helps someone.

Categories

Resources