Json change key to value - javascript

I'm looking for a way in javascript to transform this json to something else.
{
"John Doe": {
"place": "Amsterdam"
},
"Jane Doe": {
"place": "Paris"
}
}
To something like this:
{
{ "id": 0,
"name": "John Doe",
"place": "Amsterdam"
},
{ "id": 1,
"name": "Jane Doe",
"place": "Paris"
},
}
How can I achieve this with javascript?

You can use Object.entries to get key/value pair and use map method to transform the object into the new one.
const data = {
"John Doe": {
"place": "Amsterdam"
},
"Jane Doe": {
"place": "Paris"
}
}
const result = Object.entries(data).map(([key, value], index) => ({
id: index,
name: key,
place: value.place
}))
console.log(result)

You can map the entries to objects. You can mix destructuring and object property shorthand to simplify this greatly.
Note: Order is not guaranteed when iterating through an object's keys.
const obj = {
"John Doe": { "place": "Amsterdam" },
"Jane Doe": { "place": "Paris" },
};
const list = Object.entries(obj)
.map(([name, { place }], id) =>
({ id, name, place }));
console.log(list);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Related

how to get all the values inside JSON with a common name?

I need to get an array of all the name values from a JSON structure.
My JSON looks like this:
{
"profile": {
"G5j7": {
"name": "siddharth",
"age": "17"
},
"Loj9": {
"name": "ram",
"age": "20"
},
"Huy8": {
"name": "maix"
}
}
}
I can get a specific name value by:
var singleName = profile.G5j7.name;
But how do I get an array of all the name values if don't know all the IDs inside profile? I need to store in a variable.
const arrayName = Object.values(profile).map((item) => item.name);
You can use Object.getOwnPropertyNames. This function getting field names from in object to array.
let data = { "profile": { "G5j7": { "name": "siddharth", "age": "17" }, "Loj9": { "name": "ram", "age": "20" }, "Huy8": { "name": "maix" } } }
let propNames = Object.getOwnPropertyNames(data.profile)
propNames.forEach((propname) => { console.log(data.profile[propname].name) })
Object.values(yourObj.profile).map(v => v.name)
Object.values() returns an array of the values on every (own) prop of your object. So you can forget about the property names and iterate on its values
You can use Object.keys to get all properties keys in an Object, with that you can get access to all profile object keys with that you can retrieve name for each key like bellow
let data = {
"profile": {
"G5j7": {
"name": "siddharth",
"age": "17"
},
"Loj9": {
"name": "ram",
"age": "20"
},
"Huy8": {
"name": "maix"
}
}
};
let profiles_keys = Object.keys(data.profile);
let results = profiles_keys.reduce((accumulator, current)=> {
return accumulator.concat(data.profile[current].name)
}, []);
console.log(results);
let data = {
"profile":
{ "G5j7": { "name": "siddharth", "age": "17" },
"Loj9": { "name": "ram", "age": "20" },
"Huy8": { "name": "maix" }
}
};
for (const [key, value] of Object.entries(data.profile)) {
console.log(`${value.name}`);
}
You can do like this:
const names = Object.values(profile).map((profile) => profile.name);
Object.values() returns an array of the values.
Then for each profile, use .map() to get each name.
const decodedJsonObject = " { "profile": { "G5j7": { "name": "siddharth", "age": "17" }, "Loj9": { "name": "ram", "age": "20" }, "Huy8": { "name": "maix" } } }"
var singleName = profile.G5j7.name;

How do I return an array of objects that only contains a certain object in an array for Javascript?

I have an array of object called actors:
const actors = [{
"name": "John Doe",
"rating": 1234,
"alternative_name": null,
"objectID": "551486300"
},
{
"name": "Jane Doe",
"rating": 4321,
"alternative_name": "Monica Anna Maria Bellucci",
"objectID": "551486310"
}];
I specifically want to get the name and the ratings of the actors.
I tried getting it by making a function called actorNameRating, but my code does not work.
const nameAndRating = function() {
const actorName = nameAndRating.filter(name);
return actorName;
const actorRating = nameAndRating.filter(rating);
return actorRating;
};
You can do by map a function and return only name and rating:
const actors = [{
"name": "John Doe",
"rating": 1234,
"alternative_name": null,
"objectID": "551486300"
},
{
"name": "Jane Doe",
"rating": 4321,
"alternative_name": "Monica Anna Maria Bellucci",
"objectID": "551486310"
}];
const nameAndRating = function() {
return actors.map(actor => ({
name : actor.name,
rating : actor.rating
}))
};
console.log(nameAndRating())
any thing after the return will not be executed you can return both values as one string then separate it
for example :
const nameAndRating = function() {
const actorName = nameAndRating.filter(name);
const actorRating = nameAndRating.filter(rating);
return actorName+","+actorRating;
};
or any other way you find better for you to use

Object transformation using a functional approach

I am reading a simple data set from a data.txt file. I would like to take this data and transform it into a specific object as per my example below. I have managed to get it into a somewhat usable JSON object but this is not ideal. I have included an example of the desired object.
Here is my app.js file:
let output = fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n')
.map((line) => line.split(';'))
.reduce((customers, line) => {
customers.push({
name: line[0],
product: [{
item: line[1],
serial: line[2],
year: line[3]
}]
})
return customers
}, [])
console.log(JSON.stringify(output, null, 2))
This currently the above NodeJs code returns the following array object:
[
{
"name": "Nancy",
"product": [
{
"item": "Macbook Pro",
"serial": "A34D05980FCD4303",
"year": "2019"
}
]
},
{
"name": "Nancy",
"product": [
{
"item": "iPad",
"serial": "O0403X3028423C92",
"year": "2015"
}
]
},
{
"name": "Nancy",
"product": [
{
"item": "iPhone",
"serial": "X3830238S3309230",
"year": "2017"
}
]
},
{
"name": "John",
"product": [
{
"item": "Macbook Pro",
"serial": "X2020J393983H380",
"year": "2013"
}
]
},
{
"name": "John",
"product": [
{
"item": "iPhone",
"serial": "X38320093X032309",
"year": "2015"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iMac",
"serial": "F392D392033X3232",
"year": "2013"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iPad",
"serial": "FE322230D3223S21",
"year": "2011"
}
]
}
]
What I am trying to do is get the below object returned - ideally still following the same functional approach:
[
{
"name": "Nancy",
"product": [
{
"item": "Macbook Pro",
"serial": "A34D05980FCD4303",
"year": "2019"
},
{
"item": "iPad",
"serial": "O0403X3028423C92",
"year": "2015"
},
{
"item": "iPhone",
"serial": "X3830238S3309230",
"year": "2017"
}
]
},
{
"name": "John",
"product": [
{
"item": "Macbook Pro",
"serial": "X2020J393983H380",
"year": "2013"
},
{
"item": "iPhone",
"serial": "X38320093X032309",
"year": "2015"
}
]
},
{
"name": "fluffikins",
"product": [
{
"item": "iMac",
"serial": "F392D392033X3232",
"year": "2013"
},
{
"item": "iPad",
"serial": "FE322230D3223S21",
"year": "2011"
}
]
}
]
Here is my mock data set that lives in data.txt
Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011
Instead of an array you can use Map in reduce as accumulator, use name as key in Map and club value of all keys, finally just get the values Map to get desired output
const data = `Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011`
const final = data.split('\n')
.map(v => v.split(';'))
.reduce((op, [name, item, serial, year]) => {
let obj = { item, serial, year }
if (op.has(name)) {
op.get(name).products.push(obj)
} else{
op.set(name,{name, products:[obj]})
}
return op
}, new Map())
console.log([...final.values()])
Here is a "functional version" that utilizes a Map to find duplicates in O(1):
(map => (
fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n')
.map((line) => line.split(';'))
.forEach(([name, item, serial, year]) =>
map.has(name)
? map.get(name).product.push({ item, serial, year })
: map.set(name, { name, product: [{ item, serial, year }] })
),
[...map.values()]
)(new Map)
But seriously, whats so bad about imperative style?:
const customers = new Map;
const entries = fs.readFileSync('./data.txt', 'UTF8')
.trim()
.split('\r\n');
for(const entry of entries) {
const [name, item, serial, year] = entry.split(";");
const product = { item, serial, year };
if(customers.has(name)) {
customers.get(name).product.push(product);
} else customers.set(name, { name, product: [product] });
}
const result = [...customers.values()];
You can modify the .reduce function to only add a new item to the array if there isn't one with that name. If there is, just add the product to that item's product array.
const data = `Nancy;Macbook Pro;A34D05980FCD4303;2019
Nancy;iPad;O0403X3028423C92;2015
Nancy;iPhone;X3830238S3309230;2017
John;Macbook Pro;X2020J393983H380;2013
John;iPhone;X38320093X032309;2015
fluffikins;iMac;F392D392033X3232;2013
fluffikins;iPad;FE322230D3223S21;2011`;
const result = data.trim()
.split('\n')
.map((line) => line.split(';'))
.reduce((customers, line) => {
const product = {
item: line[1],
serial: line[2],
year: line[3]
};
const customer = customers.find(({
name
}) => name === line[0]);
if (customer) {
customer.product.push(product);
} else {
customers.push({
name: line[0],
product: [product]
});
}
return customers
}, []);
console.log(result);

Remove "like items" objects in array based off timestamp

I have an array of (could be more than this), that has a uid and a timestamp.
My goal is to cycle through an object and if their uid is equal to each other, only keep the object with the greater timestamp.
[
{
"uid":"u55555",
"timestamp":1536273731,
"id":"8a655addf1293b6d780ff6469c0848dd",
"name":"John Doe",
},
{
"uid":"u55555",
"timestamp":1536273831,
"id":"8v8799817981mcmccm89c81282128cm2",
"name":"John Doe",
},
{
"uid":"u1111",
"timestamp":1536253940,
"id":"c8898202n2nu929n2828998228989h2h2",
"name":"Test Testerson",
},
{
"uid":"u55555",
"timestamp":1536274940,
"id":"fb990b1734e4aaea2e39315952e13123",
"name":"John Doe",
},
{
"uid":"u11111",
"timestamp":1538275741,
"id":"99s9hshs88s8g89898899898897a79s",
"name":"Test Testerson",
},
]
Does anyone know how I would do this?
I've been playing around with the following but can't get it just right.
var result = signatures.filter(function (a) {
//logic here
}, Object.create(null));
You could sort the original array by timestamp and then reduce it to only a set of unique uids using sort and reduce.
var data = [{"uid": "u55555","timestamp": 1536273731,"id": "8a655addf1293b6d780ff6469c0848dd","name": "John Doe",}, { "uid": "u55555", "timestamp": 1536273831, "id": "8v8799817981mcmccm89c81282128cm2", "name": "John Doe", }, { "uid": "u1111", "timestamp": 1536253940, "id": "c8898202n2nu929n2828998228989h2h2", "name": "Test Testerson", }, { "uid": "u55555", "timestamp": 1536274940, "id": "fb990b1734e4aaea2e39315952e13123", "name": "John Doe", }, { "uid": "u11111", "timestamp": 1538275741, "id": "99s9hshs88s8g89898899898897a79s", "name": "Test Testerson", }];
var result = data
.sort((a,b) => b.timestamp - a.timestamp) //Sort by timestamp descending
.reduce((a,i) => a.some(n=>n.uid === i.uid) ? a : [...a, i], []); //If item is already accounted for, ignore it
console.log(result);
You can create an object keyed to the guid and loop through your array adding the item to the object if it either isn't already there or the time is smaller. Then just take the values from that object:
let arr = [{"uid":"u55555","timestamp":1536273731,"id":"8a655addf1293b6d780ff6469c0848dd","name":"John Doe",},{"uid":"u55555","timestamp":1536273831,"id":"8v8799817981mcmccm89c81282128cm2","name":"John Doe",},{"uid":"u1111","timestamp":1536253940,"id":"c8898202n2nu929n2828998228989h2h2","name":"Test Testerson",},{"uid":"u55555","timestamp":1536274940,"id":"fb990b1734e4aaea2e39315952e13123","name":"John Doe",},{"uid":"u11111","timestamp":1538275741,"id":"99s9hshs88s8g89898899898897a79s","name":"Test Testerson",},]
let newArr = Object.values(
arr.reduce((obj, item) => {
if (!obj[item.uid] || obj[item.uid].timestamp < item.timestamp)
obj[item.uid] = item
return obj
}, {}))
console.log(newArr)
You could find the object and check the timestamp or add the actual object to the result set.
var array = [{ uid: "u55555", timestamp: 1536273731, id: "8a655addf1293b6d780ff6469c0848dd", name: "John Doe" }, { uid: "u55555", timestamp: 1536273831, id: "8v8799817981mcmccm89c81282128cm2", name: "John Doe" }, { uid: "u1111", timestamp: 1536253940, id: "c8898202n2nu929n2828998228989h2h2", name: "Test Testerson" }, { uid: "u55555", timestamp: 1536274940, id: "fb990b1734e4aaea2e39315952e13123", name: "John Doe" }, { uid: "u11111", timestamp: 1538275741, id: "99s9hshs88s8g89898899898897a79s", name: "Test Testerson" }],
result = array.reduce((r, o) => {
var index = r.findIndex(({ uid }) => uid === o.uid);
if (index === -1) {
return r.concat(o);
}
if (o.timestamp > r[index].timestamp) {
r[index] = o;
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This creates a new Object, which uses keys based on the UID; then populates it with only the last entries. Perhaps not the smallest code possible, but it's a method.
let sorted = {};
let original = [{
"uid": "u55555",
"timestamp": 1536273731,
"id": "8a655addf1293b6d780ff6469c0848dd",
"name": "John Doe",
},
{
"uid": "u55555",
"timestamp": 1536273831,
"id": "8v8799817981mcmccm89c81282128cm2",
"name": "John Doe",
},
{
"uid": "u11111",
"timestamp": 1536253940,
"id": "c8898202n2nu929n2828998228989h2h2",
"name": "Test Testerson",
},
{
"uid": "u55555",
"timestamp": 1536274940,
"id": "fb990b1734e4aaea2e39315952e13123",
"name": "John Doe",
},
{
"uid": "u11111",
"timestamp": 1538275741,
"id": "99s9hshs88s8g89898899898897a79s",
"name": "Test Testerson",
},
];
original.forEach((item) => {
if (sorted[item.uid] == undefined || sorted[item.uid].timestamp < item.timestamp) {
// if key doesn't exist, create it
// if key exists but timestamp is newer, replace it
sorted[item.uid] = {
uid: item.uid,
timestamp: item.timestamp,
id: item.id,
name: item.name
}
}
});
console.log(sorted);

Filtering nested array of objects

I have the following events array. For every event there is a hash as {organisation name: [{participant 1}, {participant 2}, {...}]}
"events": [
{
"Org A": [
{
"event_id": 1,
"id": 432,
"name": "John Doe",
"role": null
},
{
"event_id": 1,
"id": 312,
"name": "Jane Mow",
"role": [
"speaker"
]
}
],
}
],
I would like to filter this events array to only contain participants whose role contains speaker.
Also, when there are no speakers in the participant array, the respective organisation entry needs to be removed from the Hash (object).
To filter the array of objects, I tried using this:
_.each(events, function(event){
_.filter(event, function(p) {
_.filter(p, function(d){
return _.some(d.role, function(r){
return r == "speaker"})
})
})
})
This however doesn't work.
Try this
var data = {
"events": [{
"Org A": [{
"event_id": 1,
"id": 432,
"name": "John Doe",
"role": null
}, {
"event_id": 1,
"id": 312,
"name": "Jane Mow",
"role": [
"speaker"
]
}],
"Org B": [],
"Org C": []
}]
};
var SPEAKER = 'speaker';
var result = _.map(data.events, function (events) {
return _.chain(events)
.mapObject(function (value, key) {
return _.filter(value, function (event) {
return _.isArray(event.role) && _.indexOf(event.role, SPEAKER) >= 0;
});
})
.pick(function (value) {
return value && value.length;
})
.value();
})
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>

Categories