Scala 提取列表中相差 1 (Ints) 的邻居
Scala extract neighbours in a List who differ by 1 (Ints)
我目前正在尝试提取列表中相差 1 的邻居。例如,如果我的列表是这样的:
List(1,2,3,7,8,10,13,14)
//By extracting I want to get:
List(
List(1,2,3),
List(7,8),
List(10),
List(13,14)
)
我自己通过 foldLeft 尝试过,我觉得我很接近但到目前为止。谁能帮我?有什么建议么? ^^
太感谢了! :)
这是一个使用 foldRight
的解决方案:
val oldList = List(1, 2, 3, 7, 8, 10, 13, 14)
val newList = oldList.foldRight[List[List[Int]]](Nil)((a, b) => b match {
case (bh @ bhh :: _) :: bt if (bhh - a == 1) => (a :: bh) :: bt
case _ => (a :: Nil) :: b
})
因此我们向后迭代条目,并根据差异是否为 1 添加到现有头列表之前或添加新的头列表:
Nil
(14, ...) => (14 :: Nil) :: Nil
(13, ...) => (13 :: 14 :: Nil) :: Nil
(10, ...) => (10 :: Nil) :: (13 :: 14 :: Nil) :: Nil
...
我有一段时间没有使用 Scala,所以这可能不是最好的解决方案,但我希望你能理解。
//First Part: Separates the list into ordered pairs with tail - head == 1
val ls = List(1,2,3,7,8,10,13,14)
val lb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- ls.sorted.sliding(2)) {
if (right - left == 1) {
lb += List(left, right)
}else {
if(!lb.flatten.toList.contains(left)) lb += List(left)
}
}
println(lb.toList)
//Second Part: Merges ordered pairs (x1, y1) and (x2, y2) when y1 == y2
val finalLb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- lb.toList.sliding(2)) {
if(left.tail.contains(right.head)) {
finalLb += (left ++ right).distinct
}else{
finalLb += right
}
}
println(finalLb.toList)
产出
First Part: List(List(1, 2), List(2, 3), List(7, 8), List(10), List(13, 14))
Second Part: List(List(1, 2, 3), List(7, 8), List(10), List(13, 14))
连续的整数会随着列表索引递增,因此我们可以减去索引,它们将形成相同数字的组
val li = List(1, 2, 3, 7, 8, 10, 13, 14)
val groups = li.zipWithIndex.groupBy({case (e, i) => e - i}) // group numbers
groups.values.toList.map(_.map(_._1)) // drop indices and grouping keys
注意:这些会丢失无序初始列表的排序。对于您的情况,您可以使用 .sortBy(_.head)
重新排序
我目前正在尝试提取列表中相差 1 的邻居。例如,如果我的列表是这样的:
List(1,2,3,7,8,10,13,14)
//By extracting I want to get:
List(
List(1,2,3),
List(7,8),
List(10),
List(13,14)
)
我自己通过 foldLeft 尝试过,我觉得我很接近但到目前为止。谁能帮我?有什么建议么? ^^ 太感谢了! :)
这是一个使用 foldRight
的解决方案:
val oldList = List(1, 2, 3, 7, 8, 10, 13, 14)
val newList = oldList.foldRight[List[List[Int]]](Nil)((a, b) => b match {
case (bh @ bhh :: _) :: bt if (bhh - a == 1) => (a :: bh) :: bt
case _ => (a :: Nil) :: b
})
因此我们向后迭代条目,并根据差异是否为 1 添加到现有头列表之前或添加新的头列表:
Nil
(14, ...) => (14 :: Nil) :: Nil
(13, ...) => (13 :: 14 :: Nil) :: Nil
(10, ...) => (10 :: Nil) :: (13 :: 14 :: Nil) :: Nil
...
我有一段时间没有使用 Scala,所以这可能不是最好的解决方案,但我希望你能理解。
//First Part: Separates the list into ordered pairs with tail - head == 1
val ls = List(1,2,3,7,8,10,13,14)
val lb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- ls.sorted.sliding(2)) {
if (right - left == 1) {
lb += List(left, right)
}else {
if(!lb.flatten.toList.contains(left)) lb += List(left)
}
}
println(lb.toList)
//Second Part: Merges ordered pairs (x1, y1) and (x2, y2) when y1 == y2
val finalLb: ListBuffer[List[Int]] = new ListBuffer[List[Int]]()
for (List(left,right) <- lb.toList.sliding(2)) {
if(left.tail.contains(right.head)) {
finalLb += (left ++ right).distinct
}else{
finalLb += right
}
}
println(finalLb.toList)
产出
First Part: List(List(1, 2), List(2, 3), List(7, 8), List(10), List(13, 14))
Second Part: List(List(1, 2, 3), List(7, 8), List(10), List(13, 14))
连续的整数会随着列表索引递增,因此我们可以减去索引,它们将形成相同数字的组
val li = List(1, 2, 3, 7, 8, 10, 13, 14)
val groups = li.zipWithIndex.groupBy({case (e, i) => e - i}) // group numbers
groups.values.toList.map(_.map(_._1)) // drop indices and grouping keys
注意:这些会丢失无序初始列表的排序。对于您的情况,您可以使用 .sortBy(_.head)