Reorder a list based on example list - list

I would like to know how to reorder a list of lists based on an example list.
Here is an example to clarify my question:
["Foo", "Bar", "Something"]
That is example list, now I want to reorder the list shown below, looking only at the heads of each list inside it:
[["Something", "one", "two", "three"], ["Foo", "four", "five", "six"],
["Bar", "seven", "eight", "nine"]]
to this:
[["Foo", "four", "five", "six"], ["Bar", "seven", "eight", "nine"],
["Something", "one", "two", "three"]]
Thanks
Edit:
I've tried mapping a swap function that swaps two elements, but that won't work because I am dealing here with two lists.

Probably a very brute approach:
Prelude> let a = [["Something", "one", "two", "three"], ["Foo", "four", "five", "six"], ["Bar", "seven", "eight", "nine"]]
Prelude> let b = ["Foo", "Bar", "Something"]
Prelude> concatMap (\y -> filter (\(x:xs) -> x == y) a) b
[["Foo","four","five","six"],["Bar","seven","eight","nine"],["Something","one","two","three"]]

Another solution based on list comprehension can be :
Prelude> let a = [["Something", "one", "two", "three"], ["Foo", "four", "five", "six"], ["Bar", "seven", "eight", "nine"]]
Prelude> let b = ["Foo", "Bar", "Something"]
Prelude> let c = [ y | x<-b, y<-a, x `elem` y ]
[["Foo","four","five","six"],["Bar","seven","eight","nine"],["Something","one","two","three"]]
you can read this chapter for more explanation on how to use list comprehension: Lyah

You want to sort your list according to a custom comparison. So, let's do it! The basic comparison function should look at the index a value appears in the examples list.
import Data.List
cmpIndex :: Eq a => [a] -> [a] -> [a] -> Ordering
cmpIndex example s1 s2 = compare (indexOf s1) (indexOf s2)
where indexOf s = findIndex (head s ==) example
This is a little dangerous -- calling head is always a cause to pause. But let's assume you know something I don't and move on. We'll give names to our inputs to make the test more readable, then fire up ghci:
example = ["Foo", "Bar", "Something"]
list = [["Something", "one", "two", "three"], ["Foo", "four", "five", "six"], ["Bar", "seven", "eight", "nine"]]
*Main> sortBy (cmpIndex example) list
[["Foo","four","five","six"],["Bar","seven","eight","nine"],["Something","one","two","three"]]

Related

Group list of tuples and sum the integers

I have the following list:
List(List(("hello", "goodbye", 12), ("hello", "goodbye", 15)), List(("hello", "test", 18), ("hello", "test", 20)), List(("something", "different", 30), ("something", "different", 18)))
I would like to get the following result:
List(("hello", "goodbye", 27), ("hello", "test", 38), ("something", "different", 48))
I've tried to use .map and .groupBy, but I can't seem to find a way to get it working.
This appears to get what you're after as long as the order of result elements is unimportant.
val data =
List(List(("hello", "goodbye", 12), ("hello", "goodbye", 15)), List(("hello", "test", 18), ("hello", "test", 20)), List(("something", "different", 30), ("something", "different", 18)))
data.flatten
.groupMapReduce(tup => (tup._1,tup._2))(_._3)(_+_)
.map{case ((k1,k2),v) => (k1,k2,v)}
.toList
//res0: List[(String, String, Int)] =
// List((hello,test,38), (something,different,48), (hello,goodbye,27))
Notice that I flatten away all the inner sub-Lists and focus only on the String elements in the tuples. It's not completely clear if that's what you intend.
You can:
Flatten those lists into a single list
Group by the first two elements of each list
Reduce on the third element of each list in each group
val list = List(
List(("hello", "goodbye", 12), ("hello", "goodbye", 15)),
List(("hello", "test", 18), ("hello", "test", 20)),
List(("something", "different", 30), ("something", "different", 18))
)
val result = list.flatten.groupBy { case (s1, s2, _) => (s1, s2) }.values.map(_.reduce((s1, s2) => (s1._1, s1._2, s1._3 + s2._3)))
// List((hello,test,38), (hello,goodbye,27), (something,different,48))
If inner list can have different "keys" - you can flatten your list of lists with flatMap(identity) or flatten then group the result using first two elements of the tuples and reduce the groupping with sum:
val collection = ...
collection
.flatten
.groupMapReduce(t => (t._1, t._2))(identity)((l,r) => (l._1, l._2, l._3+r._3))
.values
.toList

Get values from map by list of keys in groovy

I have a list of strings, i would like to get values from a map, using this list of keys.
For example:
ListOfKeys = ["one", "two", "three"]
map =["one":1,"two":2,"three":3,"four":4]
I should get only the first three because they are in the map, the rest are not.
Thanks
ListOfKeys = ["one", "two", "three"]
map =["one":1,"two":2,"three":3,"four":4]
def values = ListOfKeys.collectEntries{ map[it] }
ListOfKeys = ["one", "two", "three"];
map =["one":1,"two":2,"three":3,"four":4];
result = ListOfKeys.collectEntries{[it,map[it]]}
println result

How to initial "static const char * []" in class member?[C++]

When I am doing my homework, the question ask me to finish the given class:
//Card.hpp
class Card {
private:
static const char* faceNames[totalFaces];
};
I write mycode in Card.cpp:
const char* faceNames[Card::totalFaces] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
I use VS2017 to build it, but it shows that
error LNK2001: unresolved external symbol "private: static char const * * Card::faceNames" (?faceNames#Card##0PAPBDA)
How should I do?
You can define it outside the class without specifying the size. You don't have to specify the size again. Note the :: requirement for defining members outside class.
const char* Card::faceNames[] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
Demo
You accidentally defined an unrelated array faceNames when you meant to define the static member. You need to name the class static member using :: notation:
const char* Card::faceNames[Card::totalFaces] = { "Ace", "Deuce", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };

Make assoc-id for collection conditionally in clojure

I made assoc-in like this
(defn process-pubaccess-nb [conn books]
(map #(assoc-in % [:book/publication :publication/access] (get-rules-ids % conn) ) books)
)
I want to add condition don't made assoc-in if get-rules-ids returns nil. I tried to add when-let, but I had errors.
For example if I get
(def lib [{:book/name "one" :book/pid "1" :book/publication {:publication/pid "11"} }
{:book/name "two" :book/pid "2":book/publication {:publication/pid "22"} }
{:book/name "three" :book/pid "3" }])
I want to have
({:book/name "one", :book/pid "1", :book/publication {:publication/pid "11", :publication/access "test"}}
{:book/name "two", :book/pid "2", :book/publication {:publication/pid "22", :publication/access "test"}}
{:book/name "three", :book/pid "3"})
Now I have without condition
({:book/name "one", :book/pid "1", :book/publication {:publication/pid "11", :publication/access "test"}}
{:book/name "two", :book/pid "2", :book/publication {:publication/pid "22", :publication/access "test"}}
{:book/name "three", :book/pid "3", :book/publication {:publication/access nil}})
Maxx
Amar's solution works but it isn't clear the cost of calling get-rules-ids versus pre-filtering the collection.
Here is the filtered option for posterity:
(defn process-pubaccess-nb
[conn books]
(map #(assoc-in % [:book/publication :publication/access] (get-rules-ids % conn))
(filter :book/publication books)))
Also, if the collection may be considerable in size, transducers could be more performant.
One way to do this is with if-let.
(defn process-pubaccess-nb
[conn books]
(map #(if-let [access (get-rules-ids % conn)]
(assoc-in % [:book/publication :publication/access] access)
%)
books))

How to collate list items with the same first item onto a map

I know this is probably a very simple List operation in Scala, but I'm a newbie and can't figure it out. I have a query that returns a result set with a series of values, grouped by a common id. For example:
Result Set:
[{ 1, "a", 30 },
{ 1, "b", 20 },
{ 1, "c", 22 },
{ 2, "a", 32 },
{ 2, "c", 10 }]
and what I'd like to do is put this into a map as such:
1 -> [{"a", 30}, {"b", 20}, {"c", 22}]
2 -> [{"a", 32}, {"c", 10}]
I think the collect method can be used for this but can't figure it out.
I'm not sure what the types in your data structure are, but maybe you can adapt this. This assumes you have a collection of tuples:
val items =
List((1, "a", 30),
(1, "b", 20),
(1, "c", 22),
(2, "a", 32),
(2, "c", 10))
items
.groupBy{ case (a,b,c) => a }
.mapValues(_.map{ case (a,b,c) => (b,c) })
// Map(1 -> List((a,30), (b,20), (c,22)), 2 -> List((a,32), (c,10)))
Or, more succinctly:
items.groupBy(_._1).mapValues(_.map(t => (t._2, t._3)))
The collect method is something else entirely (basically, it's map that drops non-matching values). The groupBy method is what you were really looking for.