Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Scala:将列表拆分为多个部分_List_Scala - Fatal编程技术网

List Scala:将列表拆分为多个部分

List Scala:将列表拆分为多个部分,list,scala,List,Scala,假设我有一个元组列表 val l: List[(String, String, Date)] …此列表按日期排序 val sorted = l.sortWith((a, b) => a._3 < b._3 ) val sorted=l.sortWith((a,b)=>a.33 //我们预先设置头部,以便第一对滑动副的距离为0 val lists=(sorted.head::sorted) .滑动(2) .map{案例列表(a,b)=>(b,测试(a,b))} 托利斯先生 def

假设我有一个元组列表

val l: List[(String, String, Date)] 
…此列表按日期排序

val sorted = l.sortWith((a, b) => a._3 < b._3 )
val sorted=l.sortWith((a,b)=>a.3
现在我想把这个排序的列表分成多个列表。当日期差大于3天时,应在元组之间进行拆分。有什么好的、高效的方法可以做到这一点

谢谢和问候

编辑:

以下是一个例子: 输入(已排序):

清单((“a1”、“b1”、“2016-01-30”)、(“a2”、“b2”、“2016-02-01”)、(“a3”、“b3”), “2016-02-20”)、(“a4”、“b4”、“2016-02-23”)、(“a5”、“b5”、“2016-02-25”))

预期产出:

列表(列表((“a1”、“b1”、“2016-01-30”)、(“a2”、“b2”、“2016-02-01”)、列表((“a3”、“b3”), “2016-02-20”)、(“a4”、“b4”、“2016-02-23”)、(“a5”、“b5”、“2016-02-25”))


我简化了一些类型,代码只是说明了这个概念。如果不进行
toList
转换,性能可能会更好

type MyTuple=(字符串,Int)
val排序:列表[MyTuple]=列表(
(“a”,1),
(“a”,2),
(“a”,3),
(“b”,7),
(“b”,9),
(“c”,13),
(“c”,15),
(“c”,16)
)
def测试(a:MyTuple,b:MyTuple):布尔值=b.。_2-a.。_2>3
//我们预先设置头部,以便第一对滑动副的距离为0
val lists=(sorted.head::sorted)
.滑动(2)
.map{案例列表(a,b)=>(b,测试(a,b))}
托利斯先生
def拆分(列表:列表[(MyTuple,布尔)]):列表[列表[MyTuple]]=列表匹配{
案例Nil=>Nil
案例头部::尾部=>{
val(l1,l2)=尾部跨距(!\uu2)
(标题:l1)。地图(u.u 1)::拆分(l2)
}
}
val splitLists=split(lists).map(u.map(u._1))
println(splitLists.mkString(“\n”))
输出:

List(a, a, a)
List(b, b)
List(c, c, c)

为了方便起见,我用int代替了日期,但prinicpal是一样的

   val data = List(
      ("a","a", 10),
      ("a","b", 30),
      ("a","b", 11),
      ("a","b", 33),
      ("s","c", 37),
      ("a","c", 26),
      ("a","d", 22),
      ("m","a", 18),
      ("t","a", 15)
    )
    val sortedData = data.sortWith ((a,b)=> a._3 < b._3)
    println(s"$sortedData")
    val splitPass = sortedData.foldLeft(List[(String, String,Int)](), List[List[(String, String,Int)]](), sortedData.head._3){
      case ((cl, acc, ld),nt) =>
        if (nt._3-ld>3)
          (List(nt), cl.reverse ::acc, nt._3)
        else
          (nt:: cl, acc, nt._3)
    }
    val (fl, fa, _) = splitPass
    val res = (if (fl.isEmpty) fa else fl :: fa).reverse
    println(s"$res")
结果列表如下:

List(List((a,a,10), (a,b,11)), List((t,a,15), (m,a,18)), List((a,d,22)), List((a,c,26)), List((a,b,30), (a,b,33)), List((s,c,37)))
这样做的目的是一次通过排序列表,构建一个累加器,包括(当前组中的项列表、已完成组列表、最后添加项的Int[Date])。这包含两个空列表和列表中第一项的日期

对于源列表中的每个项目,如果它接近上一个项目,则将其添加到当前组中;如果它远离上一个项目,则当前组将关闭并添加到已完成的gorups列表中,并且当前项目将成为新列表中的第一个项目,并且当前项目的日期将成为下一次检查的参考日期。如果您想在日期与当前组中最早的日期相差很远的地方中断,可以很容易地将else分支更改为通过ld而不是nt

最后,您需要将任何未完成的组添加到组的最终集合中


这两个“.反向”是必要的,因为在典型的功能样式中,列表是向后构建的(因为这样更便宜),并在完成时反转。

这里有一个非常干净的线性时间(单程)方法:

type Date = Int  // For simplicity in the example

val sorted: List[(String,String,Date)] = List(("a1", "b1", 1),
                                              ("a1", "b1", 2),
                                              ("a1", "b1", 6),
                                              ("a1", "b1", 8),
                                              ("a1", "b1", 10),
                                              ("a1", "b1", 15),
                                              ("a1", "b1", 16))

val result = sorted.sliding(2).foldLeft(Vector(Vector(sorted.head))) { 
  case (z, List(t1, t2)) => 
    if (t2._3 - t1._3 > 3) z :+ Vector(t2)
    else                   z.init :+ (z.last :+ t2)
}

result.foreach(println)
// Vector((a1,b1,1), (a1,b1,2))
// Vector((a1,b1,6), (a1,b1,8), (a1,b1,10))
// Vector((a1,b1,15), (a1,b1,16))

您可以单独处理排序为.length()的特殊情况。

哎呀,如果这是一个聚会,我还不如把我的2美分扔来扔去

sorted.init.foldRight(List(List(sorted.last))){ (tup,acc) => 
  if (acc.head.head._3 - tup._3 > /*test for time-gap here*/) 
    List(tup)::acc  // gap too big, start new sub-List
  else
    (tup::acc.head)::acc.tail  // prepend to current sub-List
}

您能给出不同情况下的预期输出吗?使用
sortBy(u._3)
而不是
sortWith
val sorted=List(l.sortBy(u 3))使用
foldRight
而不是
foldLeft
可能会重复使用
foldLeft
可以避免任何反转的需要。@Jubobs,不是真的,它只是在
反转的地方移动<代码>覆盖def foldRight[B](z:B)(op:(A,B)=>B):B=反向。foldLeft(z)((右,左)=>op(左,右))
(from)感谢您提供了这个非常紧凑而优雅的解决方案!
sorted.init.foldRight(List(List(sorted.last))){ (tup,acc) => 
  if (acc.head.head._3 - tup._3 > /*test for time-gap here*/) 
    List(tup)::acc  // gap too big, start new sub-List
  else
    (tup::acc.head)::acc.tail  // prepend to current sub-List
}