Related
I have a string that goes like this
string = "CCB"
and a list
list = ['C','C','B','CC']
How do i sort them by their appearance order in the string (high priority) and their length(lower priority). After sorted the list should be like this
list = ['C' , 'C ', 'CC' , 'B']
I'm having some problem with this. does anyone have a python function or how to implement this problem?
One method is to create tuples of the indices and length before sorting, then reducing to the original input after. Below is one such example of doing this. Note that if the index is not found, we assume that it should come at the end and then just be sorted by length.
def sortby_index_length(input, items):
def index_or_large(haystack, needle):
try:
return haystack.index(needle)
except ValueError:
return len(haystack)
indexes = list(map(lambda x: (x, index_or_large(input, x)), items))
indexes.sort(key=lambda xy: (xy[1], len(xy[0])))
return list(map(lambda x: x[0], indexes))
print(sortby_index_length("CCB", ['C','C','B','CC']))
Which gives the expected output of ['C', 'C', 'CC', 'B']. This also uses the sort function where we specify the sorting ordering to be index tie broken by length.
Is there a way I can get the dense rank for the elements in the (unsorted) array.
For e.g. if I have an array [100,200,50] --> I need the relative rank of these elements from highest to lowest e.g. output -> [2,1,3]
Tried thinking about how to use arrayEnumerateDense but to no avail.
You are right, can be used the function arrayEnumerateDense. It is applied to reverse sorted array to get the required ranks and then map them to origin array.
SELECT
[100, 200, 50, 200, 50] AS arr,
arrayReverseSort(arr) AS sorted_arr,
arrayEnumerateDense(sorted_arr) AS sorted_arr_dense,
arrayMap(x -> (sorted_arr_dense[indexOf(sorted_arr, x)]), arr) AS arr_dense
FORMAT Vertical
/* Result
Row 1:
──────
arr: [100,200,50,200,50]
sorted_arr: [200,200,100,50,50]
sorted_arr_dense: [1,1,2,3,3]
arr_dense: [2,1,3,1,3]
*/
The same result can be got without using arrayEnumerateDense:
SELECT
[100, 200, 50, 200, 50] AS arr,
arrayReverseSort(arrayDistinct(arr)) AS sorted_dist_arr,
arrayMap(x -> indexOf(sorted_dist_arr, x), arr) AS arr_dense
FORMAT Vertical
/* Result
Row 1:
──────
arr: [100,200,50,200,50]
sorted_dist_arr: [200,100,50]
arr_dense: [2,1,3,1,3]
*/
Given a list of tuples:
val mylist = List(('orange', 0.9, 10), ('apple', 0.8, 10), ('mellon', 0.7, 10),
('car', 0.5, 2), ('truck', 0.5, 2),('tablet', 0.3, 3))
I would like to sort them in descending order with respect to the second element of the tuple. However, I would like to pick them by category, one at a time (third element) alternatively. The output should be the following list:
('orange', 0.9, 10)
('car', 0.5, 2)
('tablet', 0.3, 3)
('apple', 0.8, 10)
('truck', 0.5, 2)
('mellon', 0.7, 10)
What would be the functional way of doing it in Scala?
PS: Notice that the the result must reflect the ordering of the third element, that is, 10 appears before 2, and 2 before 3.
You can do this by adding two indices to each item in the list:
The item's category position among all existing categories (i.e. 0 for category 10, 1 for 2 and 2 for 3)
The item's index within its category by descending value of the second tuple element
Once these are added, you can order by them both (with the index withn the category taking precedence)
// traverse once to get a map of Category -> CategoryIndex
val categoryOrder: Map[Int, Int] = mylist.map(_._3).distinct.zipWithIndex.toMap
val result: List[(String, Double, Int)] = mylist
.groupBy(_._3).mapValues(_.sortBy(-_._2).zipWithIndex) // add the index of each item within its category
.toList.flatMap(_._2) // remove group keys and flatMap to get back to tuples
.sortBy { case (t, indx) => (indx, categoryOrder(t._3)) } // order by index in category and category index
.map(_._1) // remove indices
println(result)
// List((orange,0.9,10), (car,0.5,2), (tablet,0.3,3), (apple,0.8,10), (truck,0.5,2), (mellon,0.7,10))
I have two arrays, each containing any number of hashes with identical keys but differing values:
ArrayA = [{value: "abcd", value_length: 4, type: 0},{value: "abcdefgh", value_length: 8, type: 1}]
ArrayB = [{value: "ab", value_length: 2, type: 0},{value: "abc", value_length: 3, type: 1}]
Despite having any number, the number of hashes will always be equal.
How could I find the largest :value_length for every hash whose value is of a certain type?
For instance, the largest :value_length for a hash with a :type of 0 would be 4. The largest :value_length for a hash with a :type of 1 would be 8.
I just can't get my head around this problem.
A simple way:
all = ArrayA + ArrayB # Add them together if you want to search both arrays.
all.select{|x| x[:type] == 0}
.max_by{|x| x[:value_length]}
And if you wanna reuse it just create a function:
def find_max_of_my_array(arr,type)
arr.select{|x| x[:type] == type}
.max_by{|x| x[:value_length]}
end
p find_max_of_my_array(ArrayA, 0) # => {:value=>"abcd", :value_length=>4, :type=>0}
I'm not totally sure I know what the output you want is, but try this. I assume the arrays are ordered so that ArrayA[x][:type] == ArrayB[x][:type] and that you are looking for the max between (ArrayA[x], ArrayB[x]) not the whole array. If that is not the case, then the other solutions that concat the two array first will work great.
filtered_by_type = ArrayA.zip(ArrayB).select{|x| x[0][:type] == type }
filtered_by_type.map {|a| a.max_by {|x| x[:value_length] } }
Here's how I approached it: You're looking for the maximum of something, so the Array#max method will probably be useful. You want the actual value itself, not the containing hash, so that gives us some flexibility. Getting comfortable with the functional programming style helps here. In my mind, I can see how select, map, and max fit together. Here's my solution which, as specified, returns the number itself, the maximum value:
def largest_value_length(type, hashes)
# Taking it slowly
right_type_hashes = hashes.select{|h| h[:type] == type}
value_lengths = right_type_hashes.map{|h| h[:value_length]}
maximum = value_lengths.max
# Or, in one line
#hashes.select{|h| h[:type] == type}.map{|h| h[:value_length]}.max
end
puts largest_value_length(1, ArrayA + ArrayB)
=> 8
You can also sort after filtering by type. That way you can get smallest, second largest etc.
all = ArrayA + ArrayB
all = all.select { |element| element[:type] == 1 }
.sort_by { |k| k[:value_length] }.reverse
puts all[0][:value_length]
#8
puts all[all.length-1][:value_length]
#3
If A has the Ordered[A] trait, I'd like to be able to have code that works like this
val collection: List[List[A]] = ... // construct a list of lists of As
val sorted = collection sort { _ < _ }
and get something where the lists have been sorted in lexicographic order. Of course, just because A has the trait Ordered[A] doesn't mean that List[A] has the trait Ordered[List[A]]. Presumably, however, the 'scala way' to do this is with an implicit def.
How do I implicitly convert a List[A] to a Ordered[List[A]], assuming A has the trait Ordered[A] (so that the code above just works)?
I have in mind using the lexicographic ordering on List[A] objects, but I'd like code that can be adapted to others orderings.
Inspired by Ben Lings' answer, I managed to work out what seems like the simplest way to sort lists lexicographically: add the line
import scala.math.Ordering.Implicits._
before doing your List[Int] comparison, to ensure that the implicit function infixOrderingOps is in scope.
(11 minutes ago I actually didn't know how to do this, I hope it's considered okay to answer my own question.)
implicit def List2OrderedList[A <% Ordered[A]](list1: List[A]): Ordered[List[A]] = {
new Ordered[List[A]] {
def compare(list2: List[A]): Int = {
for((x,y) <- list1 zip list2) {
val c = x compare y
if(c != 0) return c
}
return list1.size - list2.size
}
}
}
An important thing to note here is the 'view bound' A <% Ordered[A], which ensures that A needn't itself by an Ordered[A], just that there's a way to do this conversion. Happily, the Scala library's object Predef has an implicit conversion from Ints to RichInts, which in particular are Ordered[Int]s.
The rest of the code is just implementing lexicographic ordering.
Inspired by Ben Lings' answer, I wrote my own version of sort:
def sort[A : Ordering](coll: Seq[Iterable[A]]) = coll.sorted
which is equivalent to:
def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
Note that ordering is implicitly converted to Ordering[Iterable[A]].
Examples:
scala> def sort[A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A]) = coll.sorted
sort: [A](coll: Seq[Iterable[A]])(implicit ordering: Ordering[A])Seq[Iterable[A]]
scala> val coll = List(List(1, 3), List(1, 2), List(0), Nil, List(2))
coll: List[List[Int]] = List(List(1, 3), List(1, 2), List(0), List(), List(2))
scala> sort(coll)
res1: Seq[Iterable[Int]] = List(List(), List(0), List(1, 2), List(1, 3), List(2))
It was asked how to supply your own comparison function (say, _ > _ instead of _ < _). It suffices to use Ordering.fromLessThan:
scala> sort(coll)(Ordering.fromLessThan(_ > _))
res4: Seq[Iterable[Int]] = List(List(), List(2), List(1, 3), List(1, 2), List(0))
Ordering.by allows you to map your value into another type for which there is already an Ordering instance. Given that also tuples are ordered, this can be useful for lexicographical comparison of case classes.
To make an example, let's define a wrapper of an Int, apply Ordering.by(_.v), where _.v extracts the underlying value, and show that we obtain the same result:
scala> case class Wrap(v: Int)
defined class Wrap
scala> val coll2 = coll.map(_.map(Wrap(_)))
coll2: List[List[Wrap]] = List(List(Wrap(1), Wrap(3)), List(Wrap(1), Wrap(2)), List(Wrap(0)), List(), List(Wrap(2)))
scala> sort(coll2)(Ordering.by(_.v))
res6: Seq[Iterable[Wrap]] = List(List(), List(Wrap(0)), List(Wrap(1), Wrap(2)), List(Wrap(1), Wrap(3)), List(Wrap(2)))
Finally, let's do the same thing on a case class with more members, reusing the comparators for Tuples:
scala> case class MyPair(a: Int, b: Int)
defined class MyPair
scala> val coll3 = coll.map(_.map(MyPair(_, 0)))
coll3: List[List[MyPair]] = List(List(MyPair(1,0), MyPair(3,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(0,0)), List(), List(MyPair(2,0)))
scala> sort(coll3)(Ordering.by(x => (x.a, x.b)))
res7: Seq[Iterable[MyPair]] = List(List(), List(MyPair(0,0)), List(MyPair(1,0), MyPair(2,0)), List(MyPair(1,0), MyPair(3,0)), List(MyPair(2,0)))
EDIT:
My definition of sort above is deprecated in 2.13:
warning: method Iterable in object Ordering is deprecated (since 2.13.0):
Iterables are not guaranteed to have a consistent order; if using a type
with a consistent order (e.g. Seq), use its Ordering (found in the
Ordering.Implicits object)
Use instead:
def sort[A](coll: Seq[Seq[A]])(implicit ordering: Ordering[A]) = {
import Ordering.Implicits._
coll.sorted
}
In 2.8, you should be able to just do collection.sorted. sorted takes an implicit Ordering parameter. Any type that implements Ordered has a corresponding Ordering (thanks to the implicit conversion Ordering.ordered). There is also the implicit Ordering.Iterable that makes an Iterable[T] have an Ordering if T has an Ordering.
However, if you try this it doesn't work:
scala> def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
<console>:5: error: could not find implicit value for parameter ord: Ordering[List[A]]
def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted
^
You need to explicitly specify that you want the Ordering[Iterable[A]]:
def sort[A <: Ordered[A]](coll: List[List[A]]) = coll.sorted[Iterable[A]]
I'm not sure why the compiler can't find the Ordering[Iterable[A]] if the element type of the collection is List[A].
Inspired by Daniel's comment, here is a recursive version:
implicit def toOrdered[A <% Ordered[A]](list1: List[A]): Ordered[List[A]] = {
#scala.annotation.tailrec
def c(list1:List[A], list2:List[A]): Int = {
(list1, list2) match {
case (Nil, Nil) => 0
case (x::xs, Nil) => 1
case (Nil, y::ys) => -1
case (x::xs, y::ys) => (x compare y) match {
case 0 => c(xs, ys)
case i => i
}
}
}
new Ordered[List[A]] {
def compare(list2: List[A]): Int = c(list1, list2)
}
}
With respect to the comment:
I used to think it's more a matter of taste. Sometimes it's easier to verify correctness on a recursive function, and certainly your version is short enough that there is no compelling reason to prefer recursive.
I was intrigued by the performance implications though. So I tried to benchmark it: see http://gist.github.com/468435. I was surprised to see that the recursive version is faster (assuming I did the benchmark correctly). The results still hold true for list of about length 10.
Just because I already implemented this another way, here is a non-recursive version that does not use return:
new Ordering[Seq[String]]() {
override def compare(x: Seq[String], y: Seq[String]): Int = {
x.zip(y).foldLeft(None: Option[Int]){ case (r, (v, w)) =>
if(r.isDefined){
r
} else {
val comp = v.compareTo(w)
if(comp == 0) None
else Some(comp)
}
}.getOrElse(x.size.compareTo(y.size))
}
}