What is preferred way to implement uniq or uniqBy filter for Array/List? - purescript

There seems no straight implementing uniq or uniqBy filter for Array/List
["val1", "val2", "val1"] -> ["val1", "val2"]
["key1" /\ 1, "key2" /\ 10, "key1" /\ 20] -> ["key1" /\ 1, "key2" /\ 10]
There can be many ways of doing this, but what is the preferred/better way to in terms of performance/simplicity?

Related

Scala merge list of maps

Input =
val data = List(
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 2))),
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 0),
Map("id" -> "hindi", "status" -> 0))))
Expected Output:
val data = List(
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 2),
Map("id" -> "hindi", "status" -> 1),
Map("id" -> "english", "status" -> 0),
Map("id" -> "hindi", "status" -> 0))))
I'm trying to merge the "sub" key values into a list without removing the old keys but I couldn't able to get it. can anyone please help with this using scala.
Start by creating some case classes. It is much easier to work with these than with maps.
case class Person(id: String, name: String, sub: List[Language])
case class Language(id: String, status: Int)
Now, create a list of Person:
val data = List(
Person("123", "raju", List(Language("english", 2))),
Person("123", "raju", List(Language("english", 0), Language("hindi", 0))))
I don't know what your merging logic is, but let's say you just want to concatenate the sub-lists for persons with the same ID. You could do it this way:
// Gets a map from ID to the list of persons with that ID
data.groupBy(_.id)
// Gets a List[List[Person]] (the values of the map)
.values
// Makes a new Person out of the inner list of persons, concatenating all the languages of that person.
.map(persons => Person(
persons.head.id,
persons.head.name,
persons.flatMap(_.sub)))
Here is example that works on pure Maps/Lists like in your example.
val data = List(
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 2))),
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 0),
Map("id" -> "hindi", "status" -> 0))))
val expected = List(
Map("id" -> "123", "name" -> "raju",
"sub" -> List(Map("id" -> "english", "status" -> 2),
Map("id" -> "hindi", "status" -> 1),
Map("id" -> "english", "status" -> 0),
Map("id" -> "hindi", "status" -> 0))))
val res = data.groupBy(x => (x.get("id"), x.get("name"))).collect { case (_, items) =>
items.reduceLeft { (l, r) =>
l.updated("sub", l("sub").asInstanceOf[List[_]] ++ r("sub").asInstanceOf[List[_]])
}
}
println(res)
https://scalafiddle.io/sf/FBj4Mvi/0
PS: To be honest creating typed structure (as proposed by others) is probably still better sollution.

Counting (optional) reviews using mongo

I am new to mongo so please forgive me for any naiveness. The following is how my database collection is formatted:
{
”id” : s t r i n g
”Reviews ” : [ {
”R a tin g s ” : {
”S e r v i c e ” ( o p ti o n al ) : numeric ,
”Cleanliness” (optional ) : numeric ,
”Overall” : numeric ,
”Value” (optional) : numeric ,
”SleepQuality” (optional ) : numeric ,
”Rooms” ( o p ti o n al ) : numeric ,
”Location” (optional) : numeric
} ,
”AuthorLocation” : string ,
”T i t l e ” : s t ri n g ,
”Author” : s t ri n g ,
”ReviewID” : s t ri n g ,
”Content ” : s t ri n g ,
”Date” : ISODate ( )
}],
”H o t el I n f o ” : {
”Name” : s t ri n g ,
"HotelURL” : s t ri n g ,
"P ri c e ” : s t ri n g ,
”Address ” : s t ri n g ,
”HotelID ” : s t ri n g ,
”ImgURL” : s t r i n g
}
}
My goal is to count the amount of ratings each restaurant has. I tried the following:
db.reviews.aggregate(
{$group : {_id: "$HotelInfo.Name", total: {$sum : "$Reviews.Ratings"}
}}
)
However this is printing 0 for the total. Any ideas as to why this isn't working and a hint towards how to get it to work.
You can try unwinding Reviews array and using the $add operator:
db.sample.aggregate([
{$unwind: "$Reviews"},
{$group: {_id: "$HotelInfo.Name", total: {$sum: {$add: [{$ifNull: ["$Reviews.Ratings.Service", 0]}, {$ifNull: ["$Reviews.Ratings.Cleanliness", 0]}, "$Reviews.Ratings.Overall", {$ifNull: ["$Reviews.Ratings.Value", 0]}, {$ifNull: ["$Reviews.Ratings.SleepQuality", 0]}, {$ifNull: ["$Reviews.Ratings.Rooms", 0]}, {$ifNull: ["$Reviews.Ratings.Location", 0]}]}}}}
])

How to use $in operator with pair of attributes

Consider this collection
/* 1 */
{
"key" : 1,
"b" : 2,
"c" : 3
}
/* 2 */
{
"key" : 2,
"b" : 5,
"c" : 4
}
/* 3 */
{
"key" : 3,
"b" : 7,
"c" : 9
}
/* 4 */
{
"key" : 4,
"b" : 7,
"c" : 4
}
/* 5 */
{
"key" : 5,
"b" : 2,
"c" : 9
}
I want to use the $in operator and write a query to return the document such (b, c) IN ((2, 3), (7, 9)). It means "return all rows where b is 2 and c is 3 at the same time, OR b is 7 and с is 9 at the same time."
How can I use $in operator to use multiple attribute values.
If I use the following query
db.getCollection('test').find({
$and:[
{b:{$in:[2,7]}},
{c:{$in:[3,9]}}
]
})
then I get following results
(2,3)
(7,9)
(2,9) --> This is unwanted record.
IN SQL world it is possible
SELECT *
FROM demo
WHERE (b, c) IN ((2, 3), (7, 9))
What is the equivalent in Mongo DB?
If I get it right, the thing you are doing is getting all the pairs (2,3),(2,9),(7,3),(7,9).
But you want to match those one by one, so your valid pairs should be (2, 3), (7, 9). To satisfy this, you can match b and c one by one, pair them and "or" them after.
db.getCollection('test').find({
$or: [
{$and: [ {b : 2}, {c : 3} ]},
{$and: [ {b : 7}, {c : 9} ]}
]
})

Scala: How to filter out maps with a common key value from a list of maps

I have a List of Map:
val input = List( Map("id" -> "abc", "val" -> 100),
Map("id" -> "abc", "val" -> 109),
Map("id" -> "bca", "val" -> 115),
Map("id" -> "acb", "val" -> 100),
Map("id" -> "cba", "val" -> 105),
Map("id" -> "cba", "val" -> 110),
Map("id" -> "cba", "val" -> 116) )
From which I need to filter out all the maps that share a common value for key "id". In other words, I have to only keep maps for which the value of key id is unique.
val output = List( Map("id" -> "bca", "val" -> 115),
Map("id" -> "acb", "val" -> 100) )
Use grouping
input.groupBy(x => x("id")).filter(y => y._2.size == 1).map(_._2)

find inside a hash mongodb

I have this struct in my collection:
{foo : 1, bar : 4, baz : {a : 1, b : 2 ,c : "fafofu"}}
How do I find "a" and "b" inside baz ?
It does not works db.my_collection.find({baz : {a : 1, b : 2});
I don't care about if "c" is "fafofu" or "cacocu" does not matters.
You can use . to reach into the baz object.
db.my_collection.find({"baz.a" : 1, "baz.b" : 2});
Perhaps if you try the following
{foo : 1, bar : 4, a: ["1"], b: ["2"], "c": ["fafofu"]}
You could use find/findOne:
print(db.???.findOne( { c: "fafofu" } ).foo);
http://www.mongodb.org/display/DOCS/Full+Text+Search+in+Mongo
Unfortunately I don't have the ability to test this.
print(db.???.baz.findOne( { c: "fafofu" } ).foo);
My problem is how to find the data, becauase if you don't know the key it is difficult to optimize the performance of your search. Wouldn't you agree?