using R.groupWith (ramda) - javascript

I'm trying to group the following array acc to dateValue, but can't seem to get it to work. What am I missing here?
const dates = [
{"id":83,"dateValue":"2017-05-24"},
{"id":89,"dateValue":"2017-05-28"},
{"id":91,"dateValue":"2017-05-25"},
{"id":78,"dateValue":"2017-05-24"},
{"id":84,"dateValue":"2017-05-25"}
]
const groups = R.groupWith(R.eqProps('dateValue'),dates)
console.log(groups)
<script src="//cdn.jsdelivr.net/ramda/latest/ramda.min.js"></script>
I've included a link to ramda repl with this code loaded
expected result:
[ [ { dateValue: "2017-05-24", id: 83 },
{ dateValue: "2017-05-24", id: 78 } ],
[ { dateValue: "2017-05-28", id: 89 } ],
[ { dateValue: "2017-05-25", id: 91 } ],
[ { dateValue: "2017-05-25", id: 84 } ] ]

There are several differences between groupBy and groupWith.
groupBy accepts a function which yields a grouping key for a single item. groupWith accepts a binary predicate that says whether two items match.
groupBy collects all items into single collections. groupWith only collects matching itemss which are consecutive.
groupBy returns an object that maps those keys to the list of matching items. groupWith returns a list of lists of (again consecutive) matching items.
It's that second point which is tripping you up. You probably want groupBy:
R.groupBy(R.prop('dateValue'))(dates)
// or
R.compose(R.values, R.groupBy(R.prop('dateValue')))(dates);
You can see this in action on the Ramda REPL.

Related

Wanna compare 2 different array list, one by user input and another list from mongodb

I have been struggling in comparing two different array lists. I need quick solution. It's really haywire to me.
What my scenario is, I wanna remove selected values, if record is not exist in another document or if exist than skip that record only and remove other records.
I made a list of objectIds input by user, when user checked the checkboxes, I am getting that id and storing in an array and making a list as given below:
"id": ["62ff99e4306e722e7201657a",
"62ffb71d2a809d528067eeca",
"62f7ce478ac4537516bdec04",
"62cb1660b851d8bb6af08aa7",
"62cb1770b851d8bb6af08ad8",]
And comparing the above array with the below document brand field:
[
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
},
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
},
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
}
]
Even if you see the second document which I am getting from mongodb has brand field which has duplicate records.
At the end what output I require is, when I click delete all button it has to delete total 3 records except below records which are matching in both arrays:
["62cb1660b851d8bb6af08aa7", "62cb1770b851d8bb6af08ad8"]
Would really appreciate if anyone solve my this issue.
I achieved opposite solution based on my question and response of #im2wddrf. Have a loook on the opposite solution.
const listCatalog = await Catalog.aggregate([
{ $project: { _id: 0, brand: 1 } }, { $unwind: "$brand" },
]);
const checkCatalog = listCatalog.map(val => {
return val.brand.toString()
});
const uniqueCatalog = _id.filter(val => {
return checkCatalog.indexOf(val) === -1
});
console.log(uniqueCatalog, "uniqueCatalog")
Here is my proposed solution:
convert your first array (let's call it asset1) to a flat array.
Then take your second array (let's call it asset2), and convert that to a flat array of arrays (no objects).
Use reduce to compare the two and keep only the common ID's that can be found.
const asset1 = {
"id": [
"62ff99e4306e722e7201657a",
"62ffb71d2a809d528067eeca",
"62f7ce478ac4537516bdec04",
"62cb1660b851d8bb6af08aa7",
"62cb1770b851d8bb6af08ad8",
]
}
const asset2 = [
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
},
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
},
{
brand: [
new ObjectId("62c95cae5db50418e6281916"),
new ObjectId("62cb1660b851d8bb6af08aa7"),
new ObjectId("62cb1770b851d8bb6af08ad8")
]
}
];
// step 1: I would convert asset1 to a simple, flat array
const mod1 = [ ...asset1.id ]
// step 2: I would convert asset2 to an array of arrays, no objects
const mod2 = asset2.map(i => {
return [ ...i.brand.map(b => b.toString()) ]
});
// now use reduce to extract only the common id's between mod1 and mod2
const result = mod2.reduce((accum, curr) => {
return accum.filter(a => curr.includes(a));
}, mod1)
console.log(mod1);
console.log(mod2);
console.log(result);

How do I access value of an attribute with an object with no key pairs?

I am working with dynamoose and a query returns me the following output
[ Document { cost: 100 },
lastKey: undefined,
count: 1,
queriedCount: undefined,
timesQueried: 1 ]
When I try to do typeof(output) , it returns Object
When I try to do Object.keys(output) , it returns [ '0', 'lastKey', 'count', 'queriedCount', 'timesQueried' ]
When I do Object.entries(output), it returns [ [ '0', Document { cost: 100 } ],[ 'lastKey', undefined ], [ 'count', 1 ], [ 'queriedCount', undefined ], [ 'timesQueried', 1 ] ]
For my use, I need to get an Object which looks like this {cost: 100} and currently I am using
JSON.parse(JSON.stringify(output))
which gives me
[ { cost: 100 } ]
I havent encountered an object without a key value pair (I'm self taught), so I do not know how to approach this problem. And the current method seems inefficient and kinda wrong. Please advice me how I can do it in a proper way
JSON.stringify(output) //=> "[ { cost: 100 } ]"
What that means is that you have an array (denoted by []) with one item, which is an object (denoted by {}) with a single key cost.
Use [0] to get the first item in an array, and then use .cost to get the cost property.
console.log(output[0].cost) //=> 100
The reason that you are seeing other keys on that array is that it looks like that dynamoose library is adding some additional properties to the array before returning it. It's doing the equivalent of:
// vanilla js, not typescript
const output = [ { cost: 100 } ]
output.count = 1
output.timesQueried = 1
This gives the array properties in addition to the content. The dynamoose library appears to use this method to encode metadata about your queries alongside the returned data.
The default JSON serialization strategy for arrays does not serialize custom array properties, only the array members.

Is this JavaScript two dimensional array?

const monsters = {
'1': {
name: 'godzilla',
age: 250000000
},
'2': {
Name: 'manticore',
age: 21
}
}
I learn JavaScript from Codecademy, What does this code mean?
Is this two dimensional array? If not, what is it?
The data structure you are showing in your code example is not an array at all, it is an object. Arrays are defined using square brackets ([]) and their keys (indices) are not explicitly declared but rather assigned automatically.
So if you wrote your code like this, for example, you would have an array containing objects:
const monsters = [
{
name: 'godzilla',
age: 250000000
},
{
name: 'manticore',
age: 21
}
]
…so you could access the values by their array index, like so.
monsters[0].name; // godzilla
monsters[1].name; // manticore

Match within a Range of two fields from an Array of Values

I have an array of numbers [111, 444, 777]
I want to look inside these 2 documents
{
_id: 1,
lookHere: {rangeLow: 333, rangeHigh: 555}
},
{
_id: 2,
lookHere: {rangeLow: 222, rangeHigh: 333}
}
I want to write a query that returns only the 1st document since my array of numbers includes 444 which is between 333 and 555.
Is there a query that can achieve this result in mongo/mongoose ?
You want an $or query. You can .map() the source array into the arguments for $or:
var inputs = [111, 444, 777];
collection.find({
"$or": inputs.map( n => ({
"lookHere.rangeLow": { "$lt": n },
"lookHere.rangeHigh": { "$gt": n }
}) )
})
That is basically looking to see if the Low value is less than and the High is greater than each of the current elements, and returns as true when any match both those conditions.
Note that all MongoDB query arguments are implicitly AND conditions unless stated otherwise.

JSON Path: Outputting value plus parent hierarchically

I'm new to JSON Path, so this may be simpler than I expect, if it's even possible.
I have a JSON block that consists of a set of groups, with each group having a set of fields. Each group also has a sequence, as does each field. The field sequence represents order within a group, and the group sequence represents the display order of the group itself.
I generated this programmatically in C# off of a flat list of items (groups and fields) with different sequence values, so I want to validate my output and, by extension, my grouping algorithm.
The JSON block looks (vastly simplified) like this:
{
"groups": [
{
"sequence": 0,
"fields": [
{
"sequence": 0
},
{
"sequence": 1
},
{
"sequence": 2
}
]
},
{
"sequence": 1,
"fields": [
{
"sequence": 0
},
{
"sequence": 1
}
]
},
{
"sequence": 2,
"fields": [
{
"sequence": 0
},
{
"sequence": 1
},
{
"sequence": 2
}
]
}
]
}
I'm trying to validate this with JSON Path. For this, I don't have a tool, so I'm using the jsonpath online evaluator.
What I'm aiming for is output along the lines of this:
'0'
'sequence' => '0'
'fields'...
'0'
'sequence' => '0'
'1'
'sequence' => '1'
'2'
'sequence' => '2'
// etc...
In other words, I'm looking for a JSON path query that can return the sequence of each group plus the sequence of each field in the group, in a hierarchy.
To get the sequence of the groups, I'm using the following. This works fine, and gives me useful output, since groups are the top-level item already:
$.groups[*].sequence
Output:
'0' => "0"
'1' => "1"
'2' => "2"
To get the sequence of the fields in the groups, I'm using the following. The output here is less useful, as it's a flat list that can get difficult to read if I have dozens or more fields spread out across several groups.
$.groups[*].fields[*].sequence
Output:
'0' => "0"
'1' => "1"
'2' => "2"
'3' => "0"
'4' => "1"
'5' => "0"
'6' => "1"
'7' => "2"
So ultimately, the question is this: is there a JSON path query that will let me get the information I need here hierarchically? Or am I using the wrong tool for the job? I suppose I could write a few lines of code in JavaScript that will let me do this if I have to, but it seems like JSON path might be a powerful tool to learn, so if I can do it here I've learned something.
You do not need a variable sequence. When you need sequence, move item from one group to another, sort you can use array in object, and object in array.
Array use to sort, move items, change sequence. Objects to grouping of attributes within a single item
var groups =
[
{"fields": [
{name: 'field1'},
{name: 'field2'},
{name: 'field3'}
],
},
{"fields": [
{name: 'field1'},
{name: 'field2'},
{name: 'field3'}
]
},
{"fields": [
{name: 'field1'},
{name: 'field2'},
{name: 'field3'}
]
}
];
console.log(groups[0].fields); // Array [ Object, Object, Object ]
console.log(groups[2].fields[0].name); // field1
Function splice is the best to change sequence. In same fields, and another fields
Example for change sequence in same fields
var oldIndex = 2, newIndex = 0, item = groups[0].fields.splice(oldIndex, 1)[0];
console.log(item);
groups[0].fields.splice(newIndex, 0, item);
console.log(groups);

Categories

Resources