Dan*_*ral 13 collections functional-programming scala
不通过索引处理集合的优点之一是避免逐个错误.这肯定不是唯一的优势,但它是其中之一.
现在,我经常用sliding在斯卡拉一些算法,但我觉得它通常会导致非常相似的off-by-一个错误的东西,因为一个sliding的m大小的集合中的元素n有大小n - m + 1的元素.或者,更简单的list sliding 2是,一个元素短于list.
我得到的感觉是,在这种模式中存在缺失的抽象,这将是一部分sliding,一部分更多 - 就像foldLeft是reduceLeft.但是,我想不出那可能是什么.任何人都可以帮我找到启示吗?
UPDATE
由于人们不清楚我在说什么,让我们考虑一下这个案例.我想大写一个字符串.基本上,每个没有字母的字母都应该是大写字母,所有其他字母应该是小写字母.使用sliding,我必须特殊情况下的第一个或最后一个字母.例如:
def capitalize(s: String) = s(0).toUpper +: s.toSeq.sliding(2).map {
  case Seq(c1, c2) if c2.isLetter => if (c1.isLetter) c2.toLower else c2.toUpper
  case Seq(_, x) => x
}.mkString
我把欧文的答案作为灵感.
如果要将简单diff()应用于列表,可以将其视为等效于以下矩阵乘法.
a = (0 1 4 3).T
M = ( 1 -1  0  0)
    ( 0  1 -1  0)
    ( 0  0  1 -1)
diff(a) = M * a = (1 3 1).T
如果我们替换加法和乘法(如果我们对矩阵M中的数字进行推广),我们现在可以使用相同的方案进行一般列表操作.
因此,使用plus作为列表追加操作(flatten后面 - 或简单地collect操作),并且乘法等价物是Some(_)或者None,窗口大小为2的幻灯片变为:
M = (Some(_) Some(_) None None)
    (None Some(_) Some(_) None)
    (None None Some(_) Some(_))
slide(a) = M “*” a = ((0 1) (1 4) (4 3)).T
不确定,如果这是你正在寻找的那种抽象,但它将是一类改变项目数量的操作的概括.
diff或者对于长度为n的输入slide的阶数m的操作将需要使用大小为n-m + 1×n的矩阵.
编辑:一个解决方案可能是转换List[A]为List[Some[A]]然后添加或附加(slideLeft或slideRight)这些None.这样你就可以处理方法中的所有魔法map.
list.slideLeft(2) {
  case Seq(Some(c1), Some(c2)) if c2.isLetter => if (c1.isLetter) c2.toLower else c2.toUpper
  case Seq(_, Some(x)) => x
}
我在 python/R/Matlab 中一直遇到这个问题,你 diff() 一个向量,然后无法将它与原始向量对齐!这是非常令人沮丧的。
我认为真正缺少的是向量仅包含因变量,并假设您(程序员)正在跟踪自变量,即集合范围的维度。
我认为解决这个问题的方法是让语言在某种程度上跟踪自变量;也许通过类型静态地进行,或者通过将它们与向量一起存储来动态地进行。然后它可以检查独立的轴,确保它们对齐,或者,我不知道这是否可能,将事物打乱以使它们对齐。
这是迄今为止我想到的最好的。
编辑
另一种思考方式是,为什么你的收藏有顺序?为什么它不只是一个集合?顺序是有意义的,但集合并没有跟踪它——它基本上使用顺序位置(其信息量与数字索引一样)来代表真正的含义。
编辑
另一个结果是像这样的变换sliding实际上代表了两种变换,一种用于因变量,另一种用于它们的轴。