一个Scala中最强大的模式是充实,我的图书馆*模式,它采用隐式转换为出现添加方法,以现有的类,而不需要动态方法解析.例如,如果我们希望所有字符串都有spaces计算他们有多少个空格字符的方法,我们可以:
class SpaceCounter(s: String) {
def spaces = s.count(_.isWhitespace)
}
implicit def string_counts_spaces(s: String) = new SpaceCounter(s)
scala> "How many spaces do I have?".spaces
res1: Int = 5
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种模式在处理泛型集合时遇到了麻烦.例如,已经询问了许多关于按顺序对项目进行分组的问题.没有内置的东西可以一次性工作,所以这似乎是使用泛型集合C和泛型元素类型的rich-my-library模式的理想候选者A:
class SequentiallyGroupingCollection[A, C[A] <: Seq[A]](ca: C[A]) {
def groupIdentical: C[C[A]] = {
if (ca.isEmpty) C.empty[C[A]]
else {
val first = ca.head
val (same,rest) = ca.span(_ == first)
same +: (new SequentiallyGroupingCollection(rest)).groupIdentical
}
}
}
Run Code Online (Sandbox Code Playgroud)
当然,除了它不起作用.REPL告诉我们:
<console>:12: error: not found: …Run Code Online (Sandbox Code Playgroud) 在Scala 2.8中,我需要调用List.min并提供我自己的比较函数来获取基于Tuple2的第二个元素的值.我不得不写这种代码:
val list = ("a", 5) :: ("b", 3) :: ("c", 2) :: Nil
list.min( new Ordering[Tuple2[String,Int]] {
def compare(x:Tuple2[String,Int],y:Tuple2[String,Int]): Int = x._2 compare y._2
} )
Run Code Online (Sandbox Code Playgroud)
有没有办法让这个更具可读性,或者像你可以用匿名函数创建一个Ordering list.sortBy(_._2)?
假设我有一个PairRDD(显然现实生活中的数据更多,假设有数百万条记录):
val scores = sc.parallelize(Array(
("a", 1),
("a", 2),
("a", 3),
("b", 3),
("b", 1),
("a", 4),
("b", 4),
("b", 2)
))
Run Code Online (Sandbox Code Playgroud)
生成具有每个键前2个分数的RDD的最有效方法是什么?
val top2ByKey = ...
res3: Array[(String, Int)] = Array((a,4), (a,3), (b,4), (b,3))
Run Code Online (Sandbox Code Playgroud) 我正在研究一种可以处理大量项目的排序/排序算法,我需要以有效的方式实现以下算法才能使其工作:
有两个数字列表.它们同样长,约100-500万件.从这里我需要找到这些列表之间的第n大产品,即.如果您创建一个矩阵,其中顶部有一个列表,那么您有另一个列表,每个单元格是上面的数字和侧面的数字的乘积.
示例:列表是A=[1, 3, 4]和B=[2, 2, 5].那么产品就是[2, 2, 5, 6, 6, 15, 8, 8, 20].如果我想要第三大,那就是8.
天真的解决方案是简单地生成这些数字,对它们进行排序然后选择第n个最大数字.但那就是O(m^2 * log m^2)m是小列表中元素的数量,而这个数字还不够快.
我认为我需要的是先对两个小清单进行排序.那是O(m * log m).然后我肯定知道最大的一个A [0]*B [0].第二大的是A [0]*B [1]或A [1]*B [0],......
我觉得这可以O(f(n))分步进行,与矩阵的大小无关.但我无法找到一种有效的方法来完成这一部分.
编辑:有一个被删除的答案,建议记住两个有序集合中的位置,然后查看A [a]*B [b + 1]和A [a + 1]*B [b],返回更大的一个并递增a/b.我会在删除之前发布此评论:
这不行.想象一下两个列表A = B = [3,2,1].这将给你像[9,6,3; 6,4,2; 3,2,1].所以你从(0,0)= 9开始,转到(0,1)= 6然后选择是(0,2)= 3或(1,1)= 4.但是,这将错过(1,0)= 6,这比两者都大.所以你不能只看两个邻居,但你必须回溯.
让这个坐标与欧几里德距离,
case class coord(x: Double, y: Double) {
def dist(c: coord) = Math.sqrt( Math.pow(x-c.x, 2) + Math.pow(y-c.y, 2) )
}
Run Code Online (Sandbox Code Playgroud)
然后让一个坐标网格
val grid = (1 to 25).map {_ => coord(Math.random*5, Math.random*5) }
Run Code Online (Sandbox Code Playgroud)
然后对于任何给定的坐标
val x = coord(Math.random*5, Math.random*5)
Run Code Online (Sandbox Code Playgroud)
最近的点x是
val nearest = grid.sortWith( (p,q) => p.dist(x) < q.dist(x) )
Run Code Online (Sandbox Code Playgroud)
所以前三个最接近的是nearest.take(3).
有没有办法让这些计算更具时间效率,特别是对于有一百万点的网格的情况?
除了len()或range()之外,请不要内置插件.我正在读期末考试.
这是我的意思的一个例子.
def find_numbers(x, lst):
lst = [3, 8, 1, 2, 0, 4, 8, 5]
find_numbers(3, lst) # this should return -> (1, 6, 7)
Run Code Online (Sandbox Code Playgroud)
我没有完全尝试过这个......无法找出解决问题的最佳方法:
def find_K_highest(lst, k):
newlst = [0] * k
maxvalue = lst[0]
for i in range(len(lst)):
if lst[i] > maxvalue:
maxvalue = lst[i]
newlst[0] = i
Run Code Online (Sandbox Code Playgroud) scala ×4
algorithm ×3
apache-spark ×1
collections ×1
kdtree ×1
performance ×1
python ×1
r-tree ×1
search ×1
sorting ×1