Compare two lists of Scala to check oneOf/Contains - scala

lets say I have 2 lists:
listOfCountries = List("United States", "Belgium", "Germany")
SecondlistOfCountries = List("Italy", "France", "Germany")
oneOf:
I want to check if there is at least one item that appears in both lists (the example will be "true")
Contains:
I want to check if one of the items in the SecondlistOfCountries list contains one of the items in the listOfCountries list (as a substring)
how would you do something like this in a clean Scala way?
thanks

oneOf can be also written as:
listOfCountries.exists(SecondlistOfCountries.contains)
For contains I suggest the same as #Tim.

oneOf:
listOfCountries.exists(SecondlistOfCountries.contains)
[ Thanks to #Ava for this version, which is much better than my original solution ]
contains:
SecondlistOfCountries.exists(c => listOfCountries.exists(c.contains))

Related

How to compare json list with another list in Gatling?

I have a json response with a list of strings. I want to check if it contains the same elements as some other list (order of those elements isn't important. How do I do that?
I tried this:
jsonPath("$.country_codes[*]").findAll.sorted.is(List("DE", "CH", "FR", "IE", "IT", "NL", "RS", "UK", "IN").sorted)
but I'm getting error "Cannot resolve symbol sorted". If I don't use 'sorted', it works, but I can't rely on getting the same order of elements from server each time..
Use transform to turn your Seq[String] into a Set[String] or sort it.

searching in mongo specifically

I have a question, lets say I have a collection called contact :
[
{"firstName": "Adam", "lastName":"Peter", "email":"adam#peter.com"},
{"firstName": "Adam", "lastName":"John", "email":"adam#john.com"},
{"firstName": "Adam", "lastName":"Petkovic", "email":"adam#petkovic.com"}
]
What I want is to search specifically, for example: I want to search "Adam peter" then I want to have a result of the first one ONLY which has Adam and peter.
I use meteor + mongo + react for my application.
Any suggestion / recommendation would be high appreciated.
Thanks for all the answers, but probably I need to ask more specific in order to get more appropriate answer.
Scenarios:
I only have 1 text box to search all the fields.
So:
when I enter "Adam", I expect to have 3 results. but when I enter "Adam Peter" I expect to have 1 result only.
When I enter "peter.com" it should have 1 result
When I enter "John", it should have 1 result
When I enter "Adam Pet" it should have 2 results.
From the answer here, below query should work fine.
db.contacts.find( { firstName: /^Adam$/i, lastName: /^peter$/i });
The query in MongoDB is case sensitive, if you want to query contact by ignoring case, you should use a regular expression, but it may not efficient.
db.contact.findOne({firstName: /^adam$/i, lastName: /^peter$/i})
it will much better if you always save these name value in lowercase, and query in lowercase
db.contact.findOne({firstName: 'adam', lastName: 'peter'})
Assuming that the rules that you are applying are:
If a single word, then that could match any field
two words mean "firstname surname"
In that case, you can't use text indices, but instead need to do some work before the mongo search.
First, split the words on whitespace, and then determine if there are one or two words. If there is one word, check that against all fields. If there are two, then only check the first word against the first name, and the second against the lastname.
// assuming input is in variable call 'term'
var words = term.trim().split(/\s+/) || [];
if(words.length === 0) {
return;
}
var first = new RegExp(words[0], 'i');
if(words.length === 2) {
var second = new RegExp(words[1], 'i');
return Contact.find({firstName: first, lastName: second});
else if(words.length === 1) {
return Contact.find({$or: [ {firstName: first}, {lastName: first}, {email: first}]})
}
Also, depending on how large your collection is, it might be better to wrap this up into a Meteor method, so that the search takes place on the server. Otherwise, you will have to publish the whole collection on the client to be able to do the search. That might be fine for a small collection though.
UPDATE:
Based on your examples, I think your rules are:
1. Search terms are combined with AND operator (e.g. Adam Pet returns two rows, not three).
2. Search terms use regular expression matching (Pet matches even though it's not any of the words).
Rule 2 means that text indices won't work, so you will need to build up a complex regex query document using $and and $or for each item:
// assuming input is in variable call 'term'
var words = term.trim().split(/\s+/) || [];
var query = {
"$and": []
};
words.forEach(function(token) {
var reg = new RegExp(token);
var innerQ = {"$or": [ {firstName: reg}, {lastName: reg}, {email: reg}]};
query["$and"].push(innerQ);
});
return Contact.find(query);

How to do text search in mgo?

I'm trying to search "efg" in field named "abc"
c.Find(bson.M{"$text": bson.M{"abc": "efg"}})
c is Collection object. I'm not getting any result. What am I doing wrong?
You are generating {$text:{abc:"efg"}}, but your query should look like this:
{$text:{$search:"efg"}}
So try updating your code to:
c.EnsureIndexKey("abc")
c.Find(bson.M{"$text": bson.M{"$search": "efg"}})
Keep in mind that to search with $text, you need to specify an index. Check out this document that explains how to use it: http://docs.mongodb.org/manual/reference/operator/query/text/
use $regex(option i for case insensitive)
example:
c.Find(bson.M{"abc": &bson.RegEx{Pattern: "efg", Options: "i"}})

Querying an array of objects

Anyone have guidance on how to query an array of hashes in coffeescript?
For example, I have an array of hashes, each with a "name" and "setting":
[
{"name":"color", "setting":"red"},
{"name":"scale_min", "setting":"15"},
{"name":"scale_type", "setting":"linear"},
{"name":"x_axis_label", "setting":"Weeks"}
]
I want to find the element in this array where the hash "name" is "x_axis_label"
How can I easily do that with coffeescript?
I need some kind of value_for_key_in_object(key, object) function and figured if would be part of the lexicon...
I just hacked this up quickly:
data = [{"name":"color","setting":"red"},{"name":"scale_min","setting":"15"},{"name":"scale_type","setting":"linear"},{"name":"x_axis_label","setting":"Weeks"}]
find = (i for i in data when i.name is 'x_axis_label')[0]
alert(find.setting)
Demo
If you going to do this repeatedly, always looking for things where the name equals something, then you are better off converting this from an array of maps to just a map where the key is the name.
data = [
{"name":"color","setting":"red"}
{"name":"scale_min","setting":"15"}
{"name":"scale_type","setting":"linear"}
{"name":"x_axis_label","setting":"Weeks"}
]
myMap = {}
for row in data
myMap[row.name] = row.setting
alert(myMap['x_axis_label'])
Demo
I always prefer a 'multi language' solution over a 'idiomatic' solution. Thus you can to use Array.filter
data = [{"name":"color","setting":"red"},{"name":"scale_min","setting":"15"},{"name":"scale_type","setting":"linear"},{"name":"x_axis_label","setting":"Weeks"}]
find = (data.filter (i) -> i.name is 'x_axis_label')[0]
alert find.setting
If you happen to be using Underscore.js, you can use find:
xAxisLabel = _.find data, (datum) -> datum.name is 'x_axis_label'

Map Reduce Tag Counts Scoped By Date And Category

I am still trying to wrap my brain around map reduce. I have a collection of articles, each of which belongs to one category, and each article has a set of keywords. Assuming that the document looks like this:
{
author: "kris",
category: "mongodb",
content: "...",
keywords: [ "keyword1", "keyword2", "keyword3" ],
created_at: "..."
}
I want to essentially pull from all documents the keyword counts, in respect to the author, so I end up with something like:
{
author: "kris",
categories: {
mongodb: { keyword1: 5, keyword2: 3, keyword3: 1 },
ruby: { ... },
python: { ... }
}
}
Any input on this would be greatly appreciated.
Thanks!
Oh, how thrilled I am by your question! This was actually part of my last assignment for my distributed systems class, so its quite fresh in my recently-graduated mind.
For the parsing details, I'd just google Apache's Hadoop tutorial, but I'll give you the general overview.
Basically, this problem requires two Map-Reduce Phases. In the first map, your input should be a list of <filename, {list of keywords}> key-value pairs (might have to do a lil preprocessing on your files, but no biggie). For each of these pairs, you output <keyword, 1> as the pair to be handed to the reducer (your basically saying every word should be counted once).
In the first reduce pass, the previous key-value pairs will conveniently be condensed so that each keyword has its own pair of the form <keyword, {1,1,1,1,1,1}>, with the number of 1s representing the number of times the word appears throughout all of the documents. So you just sum up the 1s and output <keyword, sum>.
The final map/reduce phase is just to sort the keywords by their value. Map: <keyword,sum> --> <sum,keyword> Reduce: <sum, {keywords}> --> <keyword,sum>. This exploits the fact that map-reduce sorts by key when passes to the reduce phase.
Now all of the keywords are next to their word count in sorted order!