Referencing outer SelectMany parameter from inner Select - linq

I thought I had got this to work before, but I just don't see it:
discounts is a Dictionary<PartType, double>. data is a List<PartType>.
var d = discounts.Keys.SelectMany(
k =>
data.Where( l => l.PartTypeID.Equals( k.PartTypeID ) ) )
.Select( s => new { k, l } );
The error is, the name 'k' (and 'l') does not exist in the current context.
What I eventually want to do is apply the double from the dictionary to all the matching PartTypes in data.

I suspect you mean:
var d = discounts.Keys.SelectMany(
k => data.Where(l => l.PartTypeID.Equals(k.PartTypeID)),
(k, l) => new { k, l });
... but it's hard to tell without more information. To be honest it looks like you really want a join, e.g.
var d = discounts.Keys.Join(data,
k => k.PartTypeID, // Key from discounts.Keys
l => l.PartTypeID, // Key from data
(k, l) => new { k, l }); // Projection from the two values

The l is in the context of the lambda in the Where. I think you mean s => new {k, s}. Also your parentheses seem wrong. That last parentheses on line 3 should be on line 4.

Related

Solving a recursive method

I have three variables
Group-Set of Persons ex: {{David, Sebastian, Yousef}, {Boris, Mark}}
Person-Set ex: {David, Mark, Sebastian, Boris, Yousef}
Relation-Set ex: {{David, Mark}, {Sebastian, Boris}}
A Group-Set cannot have any person that are friends with each other.
A Group-Set cannot have duplicates.
I need to create a divide method thats called
divide(person-set, relation-set) and returns a group-set as the example above.
It needs to be solved recursively and loops are not allowed.
I already have a method called areFriends(Person, Person) that returns a boolean if they are friends or not.
This is what I got so far:
divide(ps, r){
divide(ps, r, gs){
let p1 = getRandom(ps);
p2 = getRandom(ps);
if(areFriends(p1, p2) = false){
gs.add(p1);
gs.add(p2);
}
remove(p1, ps);
if(getRandom(ps) != 0){
divide(ps, r, gs);
}
}
I've been dealing with this problem for a long time now and really need help with it. Thanks!
Based on a new constraint (without no loop constraint), we need an indicator (g_ind) for considering groups in the function:
divide(ps, r, g = [[]], g_ind = 0)
p <- empty
if there is any person in ps:
p <- take the first person from ps
else:
return
if g_ind >= len(g):
// all current divisions in g have a friend of p
g.add([p]) // add a new division with initial member p
remove p from ps
divide(ps, r, g, 0)
return
else if any friends of p in r exists in g[g_ind]:
divide(ps, r, g, ++g_ind)
return
else:
g[g_ind].add(p)
remove p from ps
divide(ps, r, g, 0)
return

Scala permutations via flatMap of subset

I have the method which makes permutations:
def permutations[T](lst: List[T]): List[List[T]] = lst match {
case Nil => List(Nil)
case x :: xs => permutations(xs) flatMap { perm =>
(0 to xs.length) map { num =>
(perm take num) ++ List(x) ++ (perm drop num)
}
}
}
Firstly, it take a recursive call with pair - head, tail for List("a","b", "c"):
c - Nil
b - c
a - bc
and permute before and after parts. As result, I have all permutations from three later. My question is next: why recursive call doesn't return the intermediate statement like "bc", "cb", "c" and return valid set from three later.
Well, in each iteration you necessarily return only lists with the same size as the input list, because you return permutations of the form (perm take num) ++ List(x) ++ (perm drop num), which would always contain all of the elements in perm plus the x element.
Therefore, recursively - if each cycle returns only values of the same size as its input (including the end case of Nil), then the end result must only contain permutations of the same size.
To fix this, you can add the perm without x to each cycle's result, but you'll have to add distinct to get rid of duplications:
def permutations[T](lst: List[T]): List[List[T]] = lst match {
case Nil => List(Nil)
case x :: xs => permutations(xs) flatMap { perm =>
((0 to xs.length) flatMap { num =>
List(perm, (perm take num) ++ List(x) ++ (perm drop num))
}).distinct
}
}

Count number of elements in a list of lists

I've to adapt an existing code in Standard ML and I'm facing a problem right now.
I've got a function which is returning me a list of elements (let's call them Nodes (or Worlds))
val worlds = listNodes()
And for each world I've got a function fun listSuccessors w r which is returning the number of successors for each world.
My question is : How to obtain the number of successors globally ?
In pseudo code, I would like something like this :
worlds <-- listNodes ()
solution <-- 0
foreach w in worlds do
solution <-- solution + (length (listSuccessors w))
end foreach
return solution
But I unfortunately have no idea how to do this :/
Here are the existing functions :
fun listSuccessors w r =
let
val succs =
case Dynarraydict.get (nodes, Node.getId w)
of ROOT (_, _, succs) => succs
| _ => Exn.unexpArg "Nodestore.listSuccessors.succs"
in
List.mapPartial (fn (n, r', _) => if r = r' then SOME (getNode n) else NONE) succs
end
fun listNodes () = Dynarraydict.foldr (fn (_, ROOT item, ys) => (#1 item)::ys | (_, _, ys) => ys) nil nodes
Thanks in advance for your help :/ I'm a total beginner in Standard ML unfortunately, so it's quite complicated to understand how to manipulate list of lists. :/
Some hints : sum the size of the lists using List.fold and List.length.
In 1 single line you should be able to implement your pseudocode.
It should be some thing like :
List.fold (fun acc x -> acc+List.length x) 0 your_list_of_list.
Hmm, this looks like homework in spite of the comment, because it is a typical exercise, and a FP idiom.
A standard solution in ML (sic) is a recursive function where the parameters act as storage to sum something up or to collect some list. Other parameter(s) (the input data) diminish at every step and when empty cause the termination of the recursion.
This idiom serves the purpose to minimize the use of mutable state in the program.
Hope this helps.

sort list so that the gap between equal elements is as large as possible

Lets assume I've got an unsorted List containing a, a, b, b, a, c and I want this sequence sorted so that the gaps between equal elements are as large as possible. So in case of this sample sequence a possible output could be b, a, c, a, b, a. In my application it wouldn't be that important that the gaps are at its exact average maximum, but there shouldn't be two equal elements next to each other whenever possible. So my indention is to maximize the smallest gaps.
I'd start from measuring frequency per each unique element:
scala> val l = List("a", "a", "b", "b", "a", "c")
l: List[String] = List(a, a, b, b, a, c)
scala> val in = l.toSet[String].map(x => x -> l.count(x==)).toList.sortBy(_._2).reverse
in: List[(String, Int)] = List((a,3), (b,2), (c,1))
So now you can generate more-less scattered list:
def shuffle[T](l: List[T]) = {
def fill(n: Int, l: List[List[T]], s: T) =
l.take(n + 1).reduce(_ ++ List(s) ++ _) ++ l.drop(n + 1).flatten
val in = l.toSet[T].map(x => x -> l.count(x==)).toList.sortBy(_._2).reverse
val initial = in.head._2 -> List.fill(in.head._2)(in.head._1)
in.tail.foldLeft(initial){case ((size, acc), (value, count)) =>
count -> fill(count, acc.grouped(acc.size / size).toList, value)
}._2
}
scala> shuffle(l)
res32: List[String] = List(a, b, c, a, b, a)
Every next iteration here is based on previous one with higher frequency: elements just inserted into list (from previous iteration) as broad as possible. So it may not be so effective if frequency is dropping down significantly between iterations as high frequent elements may not be "scrumbled" enough.
This algorithm isn't trying to maximise every distance - it's trying to reduce probabilty of grouped elements appearance to the minimum. Just random shuffling should do the simillar thing if you're fine with less precise result as it produces groups with still small but a bit higher probability here:
scala> scala.util.Random.shuffle(l)
res34: List[String] = List(a, b, c, b, a, a)
As the commenter said, there is no unique solution because it depends on your cost function. My idea would be along the following line, looking only for right neighbours and assigning them a score of list.size if there is no other equal element:
def maxGaps[A](in: List[A]): List[A] = {
if (in.isEmpty) return in
def noPairs(xs: List[A]): Boolean =
xs.sliding(2, 1).forall { case List(a, b) => a != b }
val (good, bad) = in.permutations.partition(noPairs)
val candidates = if (good.nonEmpty) good else bad
val maxDist = in.size
def calcScore(xs: List[A], accum: Int = 0): Int =
xs match {
case head :: tail =>
val i = tail.indexOf(head)
val j = if (i < 0) maxDist else i
calcScore(tail, accum + j)
case Nil => accum
}
candidates.maxBy(calcScore(_))
}
maxGaps("aabbac".toList) // abacab

How to efficiently find distinct values from each column in Spark

To find distinct values from each column of an Array I tried
RDD[Array[String]].map(_.map(Set(_))).reduce {
(a, b) => (a.zip(b)).map { case (x, y) => x ++ y}}
which executes successfully. However, I'd like to know if there was a more efficient way of doing this than my sample code above. Thank you.
Aggregate saves a step, might or might not be more efficient
val z = Array.fill(5)(Set[String]()) // or whatever the length is
val d= lists.aggregate(z)({(a, b) => (a.zip(b)).map { case (x, y) => x + y}},
{(a, b) => (a.zip(b)).map { case (x, y) => x ++ y}})
You could also try using mutable sets and modifying rather than producing a new one at each step (which is explicitly allowed by Spark):
val z = Array.fill(5)(scala.collection.mutable.Set[String]())
val d= lists.aggregate(z)({(a, b) => (a.zip(b)).foreach { case (x, y) => x+= y };a},
{(a, b) => (a.zip(b)).foreach { case (x, y) => x ++= y};a})

Resources