Reducing Javascript array into a map and removing duplicate values - javascript

I am sure there is a clean way to do this, but I have no idea how to do it. I want to pluck a column out such that I am only returning the first occurrence of a value, but I want to keep the key that went with it.
I have a dataset that I want reduced. I want to pluck out the 'precip'.
Say I have this:
[
"2019-01-01" => {"temp" : "cold", "season" : "winter", "precip" : "snow"},
"2019-02-01" => {"temp" : "cold", "season" : "winter", "precip" : "none"},
"2019-03-01" => {"temp" : "mild", "season" : "spring", "precip" : "rain"},
"2019-04-01" => {"temp" : "mild", "season" : "spring", "precip" : "none"},
"2019-05-01" => {"temp" : "warm", "season" : "spring", "precip" : "rain"},
"2019-06-01" => {"temp" : "warm", "season" : "summer", "precip" : "hail"},
"2019-07-01" => {"temp" : "hot", "season" : "summer", "precip" : "none"}
]
I would like to end up with this:
[
"2019-01-01" => "snow",
"2019-02-01" => "none",
"2019-03-01" => "rain",
"2019-06-01" => "hail"
]
I would think that Array.map has something to do with this, but I don't know how to return the key/value pair instead of just a value (i.e. map(function(d) { return d.precip }) )
What is the smooth way to do this?
Thanks in advance.

You could create a Map and take only the first item with the same key.
function getFirstPrecip(data) {
return Object.assign({}, ...Array.from(
data.reduce((m, o) => {
var [[k, { precip }]] = Object.entries(o);
return m.has(precip) ? m : m.set(precip, k);
}, new Map),
([k, v]) => ({ [v]: k })
));
}
var data = [{ "2019-01-01": { temp: "cold", season: "winter", precip: "snow" } }, { "2019-02-01": { temp: "cold", season: "winter", precip: "none" } }, { "2019-03-01": { temp: "mild", season: "spring", precip: "rain" } }, { "2019-04-01": { temp: "mild", season: "spring", precip: "none" } }, { "2019-05-01": { temp: "warm", season: "spring", precip: "rain" } }, { "2019-06-01": { temp: "warm", season: "summer", precip: "hail" } }, { "2019-07-01": { temp: "hot", season: "summer", precip: "none" } }];
console.log(getFirstPrecip(data));

You can iterate the keys for the main object, and create a new object that will use those keys and assign the precip attribute value as value for the new key=>value pair:
var dates = {
"2019-01-01" : {"temp" : "cold", "season" : "winter", "precip" : "snow"},
"2019-02-01" : {"temp" : "cold", "season" : "winter", "precip" : "none"},
"2019-03-01" : {"temp" : "mild", "season" : "spring", "precip" : "rain"},
"2019-04-01" : {"temp" : "mild", "season" : "spring", "precip" : "none"},
"2019-05-01" : {"temp" : "warm", "season" : "spring", "precip" : "rain"},
"2019-06-01" : {"temp" : "warm", "season" : "summer", "precip" : "hail"},
"2019-07-01" : {"temp" : "hot", "season" : "summer", "precip" : "none"}
};
var result = Object.keys(dates).reduce((k,d) => {return [...k, {[d]:dates[d].precip}]}, [])
console.log(result)

Related

fetch data which come from firebse

I just wanted to fetch that data which coming from this https://food-ordring-af14d-default-rtdb.firebaseio.com/order the data is in the form of JSON and it looks like that
{
"-MzJLd0sSssh9tbJbjUS" : {
"orderDetails" : [ {
"amount" : 4,
"id" : "m1",
"name" : "Shushi",
"price" : 22.99
}, {
"amount" : 3,
"id" : "m2",
"name" : "Schnitzel",
"price" : 16.5
} ],
"user" : {
"address" : "A-132 shiv vihar,rishal garden,Nangloi",
"city" : "New delhi",
"name" : "Bhupender Sharma",
"postal" : "110041"
}
},
"-MzJOf_52xhRQi3izTRV" : {
"orderDetails" : [ {
"amount" : 2,
"id" : "m3",
"name" : "Barbecue Burger",
"price" : 12.99
}, {
"amount" : 2,
"id" : "m4",
"name" : "Green Bowl",
"price" : 18.99
} ],
"user" : {
"address" : "Nangloi",
"city" : "New delhi",
"name" : "ANkit",
"postal" : "445575"
}
}
}
Try this code .. here some example
const fetchdata = async()=>{
const response = await fetch('https://jsonplaceholder.typicode.com/todos')
const jdata = await response.json()
console.log(jdata)
}
fetchdata()

JSON conversion with JavaScript

This is the data I received from API but It not works with DevExtreme Grid well so I want to convert this JSON:
[{
"name" : "Cedrick Wyman",
"id" : "9101",
"children" : [ {
"name" : "Ursula Hirthe",
"id" : "9106",
"children" : [ {
"name" : "Viviane Breitenberg",
"id" : "11651"
} ]
}, {
"name" : "Twila Erdman",
"id" : "9102",
"children" : [ {
"name" : "Zion Volkman",
"id" : "9105"
}, {
"name" : "Lauryn Leannon",
"id" : "9104"
} ]
} ]
}]
To something like this with Javascript. I want to remove 'children' and move them outside
[ {
"name" : "Cedrick Wyman",
"id" : "9101"
},
{ "name" : "Ursula Hirthe",
"id" : "9106"
},
{
"name" : "Viviane Breitenberg",
"id" : "11651"
},
{
"name" : "Twila Erdman",
"id" : "9102"
},
{
"name" : "Zion Volkman",
"id" : "9105"
},
{
"name" : "Lauryn Leannon",
"id" : "9104"
}
]
How can I do this? Sorry for my bad English! Thanks a lot!
You can call .flatMap() on your array by mapping to an array of objects, which recursively calls .flatMap() on children to further get the {name, id} objects from your children array:
const arr = [{ "name": "Cedrick Wyman", "id": "9101", "children": [{ "name": "Ursula Hirthe", "id": "9106", "children": [{ "name": "Viviane Breitenberg", "id": "11651" }] }, { "name": "Twila Erdman", "id": "9102", "children": [{ "name": "Zion Volkman", "id": "9105" }, { "name": "Lauryn Leannon", "id": "9104" }] }] }];
const res = arr.flatMap(function inner({name, id, children = []}) {
return [{name, id}, ...children.flatMap(inner)];
});
console.log(res);
An alternative without .flatMap() for better browser support would be to use the following:
const arr = [{ "name": "Cedrick Wyman", "id": "9101", "children": [{ "name": "Ursula Hirthe", "id": "9106", "children": [{ "name": "Viviane Breitenberg", "id": "11651" }] }, { "name": "Twila Erdman", "id": "9102", "children": [{ "name": "Zion Volkman", "id": "9105" }, { "name": "Lauryn Leannon", "id": "9104" }] }] }];
const res = [].concat.apply([], arr.map(function inner(o) {
return [].concat.apply({name: o.name, id: o.id}, (o.children || []).map(inner));
}));
console.log(res);
The answer with flatMap is NOT supported on Internet Explorer, however my solution will work everywhere regardless of browser or server-side code.
Plus, This is more easily understandable code. You call a function recursively, until there are no children keys left in any of the items in the list.
For each item, append the name/id to flatList and if children are present, recursion starts and whatever is returned is appended to flatList preserve the desired order.
const json = [{
"name" : "Cedrick Wyman",
"id" : "9101",
"children" : [ {
"name" : "Ursula Hirthe",
"id" : "9106",
"children" : [ {
"name" : "Viviane Breitenberg",
"id" : "11651"
} ]
}, {
"name" : "Twila Erdman",
"id" : "9102",
"children" : [ {
"name" : "Zion Volkman",
"id" : "9105"
}, {
"name" : "Lauryn Leannon",
"id" : "9104"
} ]
} ]
}];
const getFlattenedList = function (unflattenedList) {
if (!(Array.isArray(unflattenedList) && unflattenedList.length)) return;
let flatList = [];
for (let i = 0; i < unflattenedList.length; i += 1) {
const item = unflattenedList[i];
flatList = flatList.concat({ name: item.name, id: item.id });
if (Array.isArray(item.children) && item.children.length) {
flatList = flatList.concat(getFlattenedList(item.children));
}
}
return flatList;
};
console.log(getFlattenedList(json));
You can do something like this:
const data = `[{
"name" : "Cedrick Wyman",
"id" : "9101",
"children" : [ {
"name" : "Ursula Hirthe",
"id" : "9106",
"children" : [ {
"name" : "Viviane Breitenberg",
"id" : "11651"
} ]
}, {
"name" : "Twila Erdman",
"id" : "9102",
"children" : [ {
"name" : "Zion Volkman",
"id" : "9105"
}, {
"name" : "Lauryn Leannon",
"id" : "9104"
} ]
} ]
}]`;
const dataJSON = JSON.parse(data);
const newData = [];
for (let e of dataJSON) {
newData.push({ name: e.name, id: e.id });
for (let child1 of e.children) {
newData.push({ name: child1.name, id: child1.id });
for (let child2 of child1.children) {
newData.push({ name: child2.name, id: child2.id });
}
}
}
console.log(newData);

Add New key at the end of each object inside an array

I have data from mongodb like this from one collection.
/* 1 */
{
"_id" : ObjectId("5be94355f220b62c7449dc0f"),
"districts" : [
{
"name" : "NORTH AND MIDDLE",
"code" : 632.0
},
{
"name" : "EAST",
"code" : 603.0
},
{
"name" : "SOUTH",
"code" : 602.0
}
],
"state" : "ISLANDS"
}
/* 2 */
{
"_id" : ObjectId("5be94355f220b62c7441dc04"),
"districts" : [
{
"name" : "Apple",
"code" : 512.0
},
{
"name" : "Ball",
"code" : 522.0
}
],
"state" : "GOLD"
}
/* 3 */
{
"_id" : ObjectId("5eee07816a011d391a45178"),
"districts" : [
{
"name" : "DAM",
"code" : 478.0
},
{
"name" : "DEN",
"code" : 481.0
},
{
"name" : "DOG AND CAT",
"code" : 461.0
}
],
"state" : "THE NAGAR AND HAVELI"
}
I was given an excel sheet like below as shown with no other information only 2 columns
My work is to add "Short Name of District" for all districts.
I tried below method
var tc = [
"NORTH AND MIDDLE",
"EAST",
"SOUTH",
"Apple",
"Ball ",
"DAM ",
"DEN ",
"DOG AND CAT"
]
db.dummy.find({"districts.name":{$in:tc}}).forEach(x => {
x["districts"].forEach( y => {
if (
y.name == "NORTH AND MIDDLE" ){
y.short_name = "NAM"
}
if (
y.name == "EAST" ){
y.short_name = "ET"
}
if (
y.name == "SOUTH" ){
y.short_name = "ST"
}
})
})
I got the result
/* 1 */
{
"_id" : ObjectId("5be94355f220b62c7449dc0f"),
"districts" : [
{
"name" : "NORTH AND MIDDLE",
"code" : 632.0,
"short_name" : "NAM"
},
{
"name" : "EAST",
"code" : 603.0,
"short_name" : "ET"
},
{
"name" : "SOUTH",
"code" : 602.0,
"short_name" : "ST"
}
],
"state" : "ISLANDS"
}
/* 2 */
{
"_id" : ObjectId("5be94355f220b62c7441dc04"),
"districts" : [
{
"name" : "Apple",
"code" : 512.0,
"short_name" : "Al"
},
{
"name" : "Ball",
"code" : 522.0
"short_name" : "BA"
}
],
"state" : "GOLD"
}
/* 3 */
{
"_id" : ObjectId("5eee07816a011d391a45178"),
"districts" : [
{
"name" : "DAM",
"code" : 478.0,
"short_name" : "DA"
},
{
"name" : "DEN",
"code" : 481.0,
"short_name" : "DN"
},
{
"name" : "DOG AND CAT",
"code" : 461.0
"short_name" : "DAC"
}
],
"state" : "THE NAGAR AND HAVELI"
}
Is this is the only method ??
like using if loop for all districts or any other methods are there like using mongodb aggregate or any other javascript methods. It will be helpful if other methods are there as it will be problem to use if loop when there is 730 districts are there. I dont have experience in working with aggregate frameworks so i thought anyone might know other method.
You may write a mapping:
const districtNameToShort = {
'NORTH AND MIDDLE': 'NAM',
'EAST': 'ET',
...
}
Then in your forEach
const districtNameToShort = {
'NORTH AND MIDDLE': 'NAM',
'EAST': 'ET'
}
db.dummy.find().forEach(x => {
db.dummy.update(
{_id : x._id},
{$set: {
districts: x.districts.map(district => {
district.short_name = districtNameToShort[district.name] || district.name
return district
})
}}
)
})

How to grab recursively data from mongo db?

I have some data (let's call it logs) in mongodb, let's say like this:
{
name: String,
category_id: String
}
Each category has parent_id. What I want is to get as up tree as possible, to the first parent and get all parents for each item of data I get from so called logs.
What I thought of first: in the controller to get all projects, then recursively get it's all parents. It'll probably works, but it seems tedious and wrong.
There is probably a better thing to do on the model itself, like a static method.
So, my question is how would you do this with mongodb? I know there are aggregations, and I used them a couple of times, but I can see how to use them if by certain field with the certain value. But here you get one project, get the next by it's parent_id and so on and so on.
You have to look at $graphLookup aggregation stage. Provide a set of relevant data for more help.
EDIT : here an example :
---DATA---
#logs collection
db.logs.find({});
{
"_id" : ObjectId("5b4f2970d42ef3178d108e86"),
"name" : "01",
"category" : "cat1"
}
{
"_id" : ObjectId("5b4f2981d42ef3178d108e87"),
"name" : "02",
"category" : "cat1"
}
{
"_id" : ObjectId("5b4f298ad42ef3178d108e88"),
"name" : "03",
"category" : "cat2"
}
{
"_id" : ObjectId("5b4f2997d42ef3178d108e89"),
"name" : "04",
"category" : "cat2"
}
{
"_id" : ObjectId("5b4f29bed42ef3178d108e8a"),
"name" : "015",
"category" : "cat10"
}
#categories collection
db.categories.find({});
{
"_id" : "cat1",
"parent_id" : "cat2"
}
{
"_id" : "cat2",
"parent_id" : "cat10"
}
{
"_id" : "cat10"
}
---AGGREGATION QUERY---
db.logs.aggregate(
[
{
$graphLookup: {
from: "categories",
startWith: "$category", // connectToField value(s) that recursive search starts with
connectFromField: "parent_id",
connectToField: "_id",
as: "related_categories",
maxDepth: 10, // optional
depthField: "depthField" // optional - name of field in output documents
}
},
],
);
---OUTPUT---
{
"_id" : ObjectId("5b4f2970d42ef3178d108e86"),
"name" : "01",
"category" : "cat1",
"related_categories" : [
{
"_id" : "cat10",
"depthField" : NumberLong(2)
},
{
"_id" : "cat2",
"parent_id" : "cat10",
"depthField" : NumberLong(1)
},
{
"_id" : "cat1",
"parent_id" : "cat2",
"depthField" : NumberLong(0)
}
]
}
{
"_id" : ObjectId("5b4f2981d42ef3178d108e87"),
"name" : "02",
"category" : "cat1",
"related_categories" : [
{
"_id" : "cat10",
"depthField" : NumberLong(2)
},
{
"_id" : "cat2",
"parent_id" : "cat10",
"depthField" : NumberLong(1)
},
{
"_id" : "cat1",
"parent_id" : "cat2",
"depthField" : NumberLong(0)
}
]
}
{
"_id" : ObjectId("5b4f298ad42ef3178d108e88"),
"name" : "03",
"category" : "cat2",
"related_categories" : [
{
"_id" : "cat10",
"depthField" : NumberLong(1)
},
{
"_id" : "cat2",
"parent_id" : "cat10",
"depthField" : NumberLong(0)
}
]
}
{
"_id" : ObjectId("5b4f2997d42ef3178d108e89"),
"name" : "04",
"category" : "cat2",
"related_categories" : [
{
"_id" : "cat10",
"depthField" : NumberLong(1)
},
{
"_id" : "cat2",
"parent_id" : "cat10",
"depthField" : NumberLong(0)
}
]
}
{
"_id" : ObjectId("5b4f29bed42ef3178d108e8a"),
"name" : "015",
"category" : "cat10",
"related_categories" : [
{
"_id" : "cat10",
"depthField" : NumberLong(0)
}
]
}

How to merge multiple documents in one. MongoDB

I want to make a new document, which get all cartItems from all orders which have the same buyer. And if it hasn't a pair (like with Leonard) it's make new doc but with status "orderId" : "merged".
For example:
It's needed for situation, when some customer will make few different orders but I need to give only one consolidated recipe.
Collection orders:
Input
{
"_id" : "001",
"buyer": "Sheldon"
"cartItems" : [
{
"itemName" : "Water",
"itemPrice" : 3
}
],
"totalCost" : 3
},
{
"_id" : "002",
"buyer" : "Sheldon",
"cartItems" : [
{
"itemName" : "Milk",
"itemPrice" : 2
}
],
"totalCost" : 2
},
{
"_id" : "003",
"buyer" : "Sheldon",
"cartItems" : [
{
"itemName" : "Butter",
"itemPrice" : 4
}
],
"totalCost" : 4
},
{
"_id" : "004",
"buyer" : "Leonard",
"cartItems" : [
{
"itemName" : "Water",
"itemPrice" : 3
}
],
"totalCost" : 3
}
Output
{
"_id" : "003_new",
"buyer" : "Sheldon",
"cartItems" : [
{
"itemName" : "Water",
"itemPrice" : 3
},
{
"itemName" : "Milk",
"itemPrice" : 2
},
{
"itemName" : "Butter",
"itemPrice" : 4
}
],
"totalCost" : 9,
"orderId" : "merged"
},
{
"_id" : "004_new",
"buyer" : "Leonard",
"cartItems" : [
{
"itemName" : "Water",
"itemPrice" : 3
}
],
"totalCost" : 3,
"orderId" : "merged"
}
Would be better if you provide example in JS.
db.orders.aggregate([
{$sort: {_id: 1, buyer: 1}},
{$unwind: '$cartItems'},
{$group: {_id: '$buyer', cartItems: {$push: '$cartItems'},
totalCost: {$sum: '$totalCost'},
id: {$last: {$concat: ["$_id", "_", "new" ]}},
buyer: {$last: '$buyer'}}},
{$addFields: {orderId: 'merged', _id: '$id'}},
{$project: {"id": 0 }}])
BTW, it's mongodb shell, but it's JS ;)

Categories