Ramda - how to merge 2 or more arrays of objects - ramda.js

I am trying to merge arrays of objects into one clean array using Ramda but I need some help. I have sample JSON which is below. In this example, I have 2 groups but the number of groups can be 3, 4, 10. I am interested in tableItems array from each group.
const groups = [
{
id: '',
name: '',
tableItems: [
{
id: 1,
name: 'John'
},
{
id: 2,
name: 'Paul'
},
{
id: 3,
name: 'Mary'
}
]
},
{
id: '',
name: '',
tableItems: [
{
id: 10,
name: 'Brian'
},
{
id: 20,
name: 'Joseph'
},
{
id: 30,
name: 'Luke'
}
]
}
];
I tried something like this:
let mapValues = x => x.tableItems;
const testItems = R.pipe(
R.map(mapValues)
)
And then I got arrays of my tableItems and now I would like to merge them into one array.
[
[
{
"id": 1,
"name": "John"
},
{
"id": 2,
"name": "Paul"
},
{
"id": 3,
"name": "Mary"
}
],
[
{
"id": 10,
"name": "Brian"
},
{
"id": 20,
"name": "Joseph"
},
{
"id": 30,
"name": "Luke"
}
]
]
Any help would be appreciated.

Use R.chain to map and flatten, and get the tableItems using R.prop:
const fn = R.chain(R.prop('tableItems'));
const groups = [{"id":"","name":"","tableItems":[{"id":1,"name":"John"},{"id":2,"name":"Paul"},{"id":3,"name":"Mary"}]},{"id":"","name":"","tableItems":[{"id":10,"name":"Brian"},{"id":20,"name":"Joseph"},{"id":30,"name":"Luke"}]}];
const result = fn(groups);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

Related

How to add a field in the mongoDB query representing a total figure

I have a mongodb query
[
{$group: {
_id: '$status',
count: {$sum: NumberInt(1)}
}}
]
The query returns the following result:
[
{ _id: "A", count: 22 },
{ _id: "B", count: 33 },
{ _id: "C", count: 44 }
]
Based on the above, I need to add a new field "totalCount" (e.g. 22 + 33 + 44 = 99) as in the following:
[
{ _id: "A", count: 22, totalCount: 99 },
{ _id: "B", count: 33, totalCount: 99 },
{ _id: "C", count: 44, totalCount: 99 }
]
Any help or clue is highly appreciated.
You have to make use of $facet stage to create multiple instances of aggregation, calculate the total count in a different stage and finally merge into a single output.
db.collection.aggregate([
{
"$facet": {
"totalCount": [
{
"$group": {
"_id": null,
"totalCount": {
"$sum": "$count"
}
},
},
],
"root": [
{
"$replaceRoot": {
"newRoot": "$$ROOT"
}
},
]
}
},
{
"$unwind": "$root"
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$root",
{
"$arrayElemAt": [
"$totalCount",
0
]
}
],
}
}
},
])
Mongo Sample Execution

ARCore Sceneform SDK linking materials Error?

I just have a simple table model has a 3 segments Top,Brick,Bottom. I applied Normal maps to the bottom part and it was successful but when i tried to apply normal map for the Brick and Top part it says, duplicate field name. I can figure it out what error it says. I was doing what says in this documentation. https://developers.google.com/sceneform/develop/sfa
{
animations: [
{
path: 'sampledata/models/sculpting-table/source/SculptingTable.fbx',
},
],
materials: [
{
name: 'TableTop',
parameters: [
{
baseColor: [
1,
1,
1,
1,
],
},
{
baseColorMap: 'SculptingTable_TableTop_AlbedoTransparency',
},
{
normalMap: null,
},
{
interpolatedColor: null,
},
{
metallic: 0,
},
{
metallicMap: null,
},
{
roughness: 1,
},
{
roughnessMap: null,
},
{
opacity: null,
},
],
source: 'build/sceneform_sdk/default_materials/fbx_material.sfm',
},
{
name: 'TableBottom',
parameters: [
{
baseColor: [
1,
1,
1,
1,
],
},
{
baseColorMap: 'SculptingTable_TableBottom_AlbedoTranspare',
},
{
normalMap: 'bumps',
},
{
interpolatedColor: null,
},
{
metallic: 0,
},
{
metallicMap: null,
},
{
roughness: 1,
},
{
roughnessMap: null,
},
{
opacity: null,
},
],
source: 'build/sceneform_sdk/default_materials/fbx_material.sfm',
},
{
name: 'TableBricks',
parameters: [
{
baseColor: [
1,
1,
1,
1,
],
},
{
baseColorMap: 'SculptingTable_TableBricks_AlbedoTranspare',
},
{
normalMap: null,
},
{
interpolatedColor: null,
},
{
metallic: 0,
},
{
metallicMap: null,
},
{
roughness: 1,
},
{
roughnessMap: null,
},
{
opacity: null,
},
],
source: 'build/sceneform_sdk/default_materials/fbx_material.sfm',
},
],
model: {
attributes: [
'Position',
'TexCoord',
'Orientation',
'BoneIndices',
'BoneWeights',
],
collision: {},
file: 'sampledata/models/sculpting-table/source/SculptingTable.fbx',
name: 'SculptingTable',
recenter: 'root',
},
samplers: [
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBricks_AlbedoTranspare.png',
name: 'SculptingTable_TableBricks_AlbedoTranspare',
pipeline_name: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBricks_AlbedoTranspare.png',
},
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBottom_AlbedoTranspare.png',
name: 'SculptingTable_TableBottom_AlbedoTranspare',
pipeline_name: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBottom_AlbedoTranspare.png',
},
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableTop_AlbedoTransparency.png',
name: 'SculptingTable_TableTop_AlbedoTransparency',
pipeline_name: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableTop_AlbedoTransparency.png',
},
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBottom_Normal.png',
name: 'bumps',
injections: [
{usage: "Normal",},
],
},
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBricks_Normal.png',
name: 'bumpsBrick',
injections: [
{usage: "Normal",},
],
},
],
version: '0.54:2',
}
About is the SFA file of the model.
Validating Materials: Validating material: Jsonnet Error: [1]: RUNTIME ERROR: duplicate field name: "Normal"
This is the log error that appears.
I got the answer we needed to add material_name attribute inside the injection block too. This will get rid of the duplication of "Normal" keyword.
{
file: '/Users/vishweshwaran/Downloads/sculpting-table/textures/SculptingTable_TableBottom_Normal.png',
name: 'bumps',
injections: [
{
material_name:"name_of_your_material",
usage: "Normal",},
],
},

Mongoose Schema - How to add an order attribute for sorting

I am currently building a web application where you can create setlists (arrays) with an array of lyric objectId's inside, that you can then sort / order into how you want it. So if you would like the 3rd list item to become the first, then you simply drag and drop it to the first line.
I now have a problem in my mongoose schema. I am looking for a way to implement an order attribute or something that would allow me to add a order value such as 0 or 1 depending on the position of the lyrics. Does any of you know how to best implement such order?
Here is a copy of my schema. Currently lyrics is an array of lyric objectId's. But in there i would need an "Order" as well, so that i can sort the array according to the order value.
const mongoose = require("mongoose");
const SetlistSchema = new mongoose.Schema({
setlistName: { type: String, required: true },
lastEdited: { type: Date },
createdAt: { type: Date, default: Date.now },
lyrics: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Lyric'
}],
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
module.exports = mongoose.model("Setlist", SetlistSchema);
Here is the Lyrics schema.
const mongoose = require("mongoose");
const LyricSchema = new mongoose.Schema({
lyricName: { type: String, required: true },
lyricContent: { type: String, required: true },
lastEdited: { type: Date },
createdAt: { type: Date, default: Date.now },
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
}
});
module.exports = mongoose.model("Lyric", LyricSchema);
If adding an order number isn't the best practice, what can you then recommend as a way of keeping track of which order the user would like the lyrics to show up?
You can use aggregation framework to sort lyrics by order field. You first need to add a sort field with Number type.
Setlist.aggregate([
{
$unwind: "$lyrics"
},
{
$lookup: {
from: "lyrics", // MUST be the PHYSICAL collection name
localField: "lyrics",
foreignField: "_id",
as: "lyrics"
}
},
{
$sort: {
"lyrics.order": 1
}
},
{
"$group": {
"_id": "$_id",
"lyrics": {
"$push": "$lyrics"
},
"allFields": {
"$first": "$$ROOT"
}
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$allFields",
{
"lyrics": "$lyrics"
}
]
}
}
}
])
Playground
Sample documents:
db={
"lists": [
{
"_id": ObjectId("5a934e000102030405000000"),
"setlistName": "list1",
"lastEdited": ISODate("2020-03-18T23:11:56.443+03:00"),
"createdAt": ISODate("2020-03-15T23:11:56.443+03:00"),
"lyrics": [
ObjectId("6a934e000102030405000000"),
ObjectId("6a934e000102030405000001"),
ObjectId("6a934e000102030405000002")
]
},
{
"_id": ObjectId("5a934e000102030405000001"),
"setlistName": "list2",
"lastEdited": ISODate("2020-03-11T23:11:56.443+03:00"),
"createdAt": ISODate("2020-03-11T23:11:56.443+03:00"),
"lyrics": [
ObjectId("6a934e000102030405000003"),
ObjectId("6a934e000102030405000004")
]
}
],
"lyrics": [
{
"_id": ObjectId("6a934e000102030405000000"),
"name": "Lyric 1",
"order": 3
},
{
"_id": ObjectId("6a934e000102030405000001"),
"name": "Lyric 2",
"order": 1
},
{
"_id": ObjectId("6a934e000102030405000002"),
"name": "Lyric 3",
"order": 2
},
{
"_id": ObjectId("6a934e000102030405000003"),
"name": "Lyric 4",
"order": 2
},
{
"_id": ObjectId("6a934e000102030405000004"),
"name": "Lyric 5",
"order": 1
}
]
}
Output: (as you see lyrics are sorted by order field value)
[
{
"_id": ObjectId("5a934e000102030405000000"),
"createdAt": ISODate("2020-03-15T20:11:56.443Z"),
"lastEdited": ISODate("2020-03-18T20:11:56.443Z"),
"lyrics": [
[
{
"_id": ObjectId("6a934e000102030405000001"),
"name": "Lyric 2",
"order": 1
}
],
[
{
"_id": ObjectId("6a934e000102030405000002"),
"name": "Lyric 3",
"order": 2
}
],
[
{
"_id": ObjectId("6a934e000102030405000000"),
"name": "Lyric 1",
"order": 3
}
]
],
"setlistName": "list1"
},
{
"_id": ObjectId("5a934e000102030405000001"),
"createdAt": ISODate("2020-03-11T20:11:56.443Z"),
"lastEdited": ISODate("2020-03-11T20:11:56.443Z"),
"lyrics": [
[
{
"_id": ObjectId("6a934e000102030405000004"),
"name": "Lyric 5",
"order": 1
}
],
[
{
"_id": ObjectId("6a934e000102030405000003"),
"name": "Lyric 4",
"order": 2
}
]
],
"setlistName": "list2"
}
]

RamdaJS groupBy and tranform object

I want to transform this array of objects using RamdaJS. From this array of objects
let children = [
{ "name": "Bob", "age": 8, "father": "Mike" },
{ "name": "David", "age": 10, "father": "Mike" },
{ "name": "Amy", "age": 2, "father": "Mike" },
{ "name": "Jeff", "age": 11, "father": "Jack" }
]
into this array of objects
let fatherAndKids = [
{
"father": "Mike",
"count" : 3,
"kids": [
{ "name": "Bob", "age": 8 },
{ "name": "David", "age": 10 },
{ "name": "Amy", "age": 2
}
]
},
{
"father": "Jack",
"count" : 1,
"kids": [
{ "name": "Jeff", "age": 11 }
]
}
]
Here's what i did so far. But i failed to remove the father keys from kids's array
R.pipe(
R.groupBy(R.prop('father')),
R.map(kids => ({
father: R.head(kids)["father"],
count: kids.length,
kids: kids
})),
R.values()
)(children)
Use R.applySpec to create the object, and use R.map with R.dissoc to remove the 'father' property:
const { pipe, groupBy, prop, applySpec, head, length, map, dissoc, values } = R
const fn = pipe(
groupBy(prop('father')),
map(applySpec({
father: pipe(head, prop('father')),
count: length,
kids: map(dissoc('father'))
})),
values
)
const children = [
{ "name": "Bob", "age": 8, "father": "Mike" },
{ "name": "David", "age": 10, "father": "Mike" },
{ "name": "Amy", "age": 2, "father": "Mike" },
{ "name": "Jeff", "age": 11, "father": "Jack" }
]
const result = fn(children)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>

How to get values in an array from nested array of objects based on a given condition?

I'm using lodash and I have the following array of objects:
[{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
}
]
}]
What i'm trying to get the list of ID and name for a given "SUB".
So, with the previous object, if I send the sub fr I want to get:
[{
"id": 1,
"name": "foobar1"
},
{
"id": 2,
"name": "foobar3"
}]
Do you know if I can easily do it with lodash?
I tried to use _.pick but it doesn't working(I'm a bit lost with these mixes between nested objects and arrays) _.map(data, function (o) { _.pick(o, ['id', 'values.name']) });.
I also tried to use _.filter with things like _.filter(data, { values: [{ sub: 'fr' }]}); but it return all the items. What I'm looking for is to return the nested part only.
You can use flatMap() where its callback returns an array of filtered subs using filter() where each filtered item is transformed using map().
var result = _.flatMap(data, item =>
_(item.values)
.filter({ sub: 'fr' })
.map(v => ({id: item.id, name: v.name}))
.value()
);
var data = [{
"id": 1,
"values": [
{
"sub": "fr",
"name": "foobar1"
},
{
"sub": "en",
"name": "foobar2"
}
]
},
{
"id": 2,
"values": [
{
"sub": "fr",
"name": "foobar3"
},
{
"sub": "en",
"name": "foobar4"
}
]
}];
var result = _.flatMap(data, item =>
_(item.values)
.filter({ sub: 'fr' })
.map(v => ({id: item.id, name: v.name}))
.value()
);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
following #ryeballar's answer, a shorter version with map
var result = _.map(data, item => ({id: item.id, name: item.name}));