2016-06-08 6 views
0

겹치는 요소가있는 튜플 목록의 목록이 있습니다.스칼라의 튜플 목록 병합 목록

val tupLis:Seq[(List[(Integer,Char)],Int)] = null//data 

튜플 목록에서 겹치는 요소를 병합하려고합니다. 여기에 어떤 코드를 사용하여 어떤 foldleft를 사용하여 목록에서 중복 된 튜플 목록을 병합합니다. 병합 작업이 수행되지 않습니다. 일부 튜플 목록 요소가 누락되어 있습니다. 각 튜플 목록에는 4 개의 튜플이 들어 있습니다. . 목록의 각 튜플 목록은 슬라이딩 기능을 사용하여 더 큰 목록에서 생성 될 때 종종 겹쳐집니다.

(List((306,c), (328,g), (336,a), (346,g)),282) 
(List((306,g), (328,c), (336,g), (346,a)),22) 
(List((306,c), (328,c), (336,g), (346,a)),4) 
(List((328,g), (336,a), (346,g), (348,t)),164) 
(List((328,g), (336,a), (346,g), (348,c)),161) 
(List((328,c), (336,g), (346,a), (348,c)),28) 
(List((336,a), (346,g), (348,t), (358,a)),168) 
(List((336,a), (346,g), (348,c), (358,a)),154) 
(List((336,g), (346,a), (348,c), (358,g)),30) 
(List((346,g), (348,t), (358,a), (361,c)),178) 
(List((346,g), (348,c), (358,a), (361,c)),166) 
(List((346,a), (348,c), (358,g), (361,g)),34) 

병합 목록 모양처럼 :

List((306,c), (328,g), (336,a), (346,g), (348,t), (358,a), (361,c),792) 
List((306,c), (328,g), (336,a), (346,g), (348,c), (358,a), (361,c)),763) 
List((306,g), (328,c), (336,g), (346,a), (348,c), (358,g), (361,g)),96) 

업데이트 1 :

오버랩 :이 개 목록의 경우 여기를

val alLis:Seq[(List[(Integer,Char)],Int)] = snGrMap.map(_._2).flatten.toList.sortBy(_._1.head._1) 
val res = alLis.foldLeft(mutable.HashMap.empty[Int,(List[Integer],List[(Integer,Char)],Int)]) { (map, value) => 
    if(map.size<=0){ 
    map.put(0,(value._1.map(_._1),value._1,value._2)) 
    }else{ 
    val cads = map.filter(p=>value._1.intersect(p._2._2).size>=3) 
    if(cads.size>=1) { 
     cads.foreach { i => 
     val cmnPos = i._2._1.intersect(value._1.map(_._1)) 
     val cmnBase = i._2._2.filter(p=>cmnPos.contains(p._1)).intersect(value._1.filter(p=>cmnPos.contains(p._1))) 
     println(cmnBase.size,cmnPos.size,value._1, i._2._2) 
     if(cmnBase.size == cmnPos.size) 
      map.put(i._1,((i._2._1++value._1.map(_._1)).distinct,(i._2._2++value._1).distinct,i._2._3+value._2)) 
     else 
      map.put(map.size,(value._1.map(_._1),value._1,value._2)) 
     } 
    }else{ 
     map.put(map.size,(value._1.map(_._1),value._1,value._2)) 
    } 
    } 
    map 
} 

내가 사용하고있는 예제 데이터입니다 튜플은 3 개 이상의 정확한 튜플을 두리스트에 모두 가지고 있습니다. 튜플의 중복 목록으로 간주됩니다. 두리스트가 병합 될 때 uld는 아무런 차이가 없어야합니다. 두리스트의 튜플 값 중 하나가 같은 정수이지만 다른 char을 갖는다면, 병합되지 않습니다. 병합 : 두 개 이상의 튜플 목록이 겹칠 때이를 조합합니다.

업데이트 2 : 나는 작은 솔루션을 생각해 냈지만 얼마나 효율적인지는 확신 할 수 없습니다.

val alLisWithIndex = alLis.zipWithIndex 
    val interGrps = new ListBuffer[(Int,Int)]() 
    alLisWithIndex.foreach{i=> 
     val cads = alLisWithIndex.filter(p=>p._1._1.take(3).intersect(i._1._1.takeRight(3)).size>=3) 
     cads.foreach(p=>interGrps.append((i._2,p._2))) 
    } 
println(interGrps.sortBy(_._1)) 

위의 코드를 인쇄 할 때 이렇게하면 튜플 목록이 그룹화됩니다. 병합해야하는 각 튜플 그룹의 인덱스 만 인쇄했습니다.

결과 생성 : ListBuffer ((0,2), (0,3), (1,4), (2,5), (3,6), (4,7), (5,8) (6,9)는 (7,10)) 여기

그래서 지금 내가해야 할 일을했을 모두가 interGrps을 사용했다

List(((List((306,c), (328,g), (336,a), (346,g)),282),0), 
((List((306,g), (328,c), (336,g), (346,a)),22),1), 
((List((328,g), (336,a), (346,g), (348,t)),164),2), 
((List((328,g), (336,a), (346,g), (348,c)),161),3), 
((List((328,c), (336,g), (346,a), (348,c)),28),4), 
((List((336,a), (346,g), (348,t), (358,a)),168),5), 
((List((336,a), (346,g), (348,c), (358,a)),154),6), 
((List((336,g), (346,a), (348,c), (358,g)),30),7), 
((List((346,g), (348,t), (358,a), (361,c)),178),8), 
((List((346,g), (348,c), (358,a), (361,c)),166),9), 
((List((346,a), (348,c), (358,g), (361,g)),34),10)) 

을 사용 자신의 인덱스 튜플의 목록은 링크입니다 두 번째 값에 따라 그룹을 만들고 마지막으로 인덱스를 튜플 목록으로 바꿉니다.

+0

병합 된 목록 (그리고 당신이 "중복"을 의미하는)의 정의는 매우 불분명하다 특히 총액을주지 않는 한. –

+0

죄송합니다, 아직 명확하지 않습니다. 동일한 정수 값을 갖는 char에 차이가있을 때 "겹치기"합니까? 거기에 "병합"을 사용하기 때문에 약간 혼란 스럽습니다. "3 개 이상의 튜플을 공유하면 두 개의 목록이 겹치고 같은 번호를 가진 튜플 쌍에는 다른 문자가 없습니까?" –

+0

예, "3 개 이상의 튜플을 공유하면 두리스트가 겹칩니다. 숫자가 같은 튜플 쌍에는 다른 문자가 없습니다" – Balaram26

답변

2

다음 코드는 알고리즘에 대한 설명입니다. 뭔가 당신이 지금 테스트 데이터

var xs = List(
(List((306,"c"), (328,"g"), (336,"a"), (346,"g")),282), 
(List((306,"g"), (328,"c"), (336,"g"), (346,"a")),22), 
(List((306,"c"), (328,"c"), (336,"g"), (346,"a")),4), 
(List((328,"g"), (336,"a"), (346,"g"), (348,"t")),164), 
(List((328,"g"), (336,"a"), (346,"g"), (348,"c")),161), 
(List((328,"c"), (336,"g"), (346,"a"), (348,"c")),28), 
(List((336,"a"), (346,"g"), (348,"t"), (358,"a")),168), 
(List((336,"a"), (346,"g"), (348,"c"), (358,"a")),154), 
(List((336,"g"), (346,"a"), (348,"c"), (358,"g")),30), 
(List((346,"g"), (348,"t"), (358,"a"), (361,"c")),178), 
(List((346,"g"), (348,"c"), (358,"a"), (361,"c")),166), 
(List((346,"a"), (348,"c"), (358,"g"), (361,"g")),34)) 

튜플이 개 목록은 3이있는 경우 "구현하는 방법

먼저, 원하는 뭐에 대해 정리하기 위해 여전히 그래서 그러나, 동일한 출력을 제공하지 않습니다 또는 두 개의리스트에 더 정확한 튜플이 있으면, 튜플의 중복 목록으로 간주됩니다."

def isOverlap[A](a:(List[A],Int),b:(List[A],Int)) = (a._1 intersect b._1).size >= 3 

그런 것을 사용 나는 here에 걸쳐 쓴 것으로 그룹 요소"술어에 따라 일치 "

def groupWith[A](xs: List[A], f: (A, A) => Boolean) = { 
    // helper function to add "e" to any list with a member that matches the predicate 
    // otherwise add it to a list of its own 
    def addtoGroup(gs: List[List[A]], e: A): List[List[A]] = { 
    val (before, after) = gs.span(_.exists(!f(_, e))) 
    if (after.isEmpty) 
     List(e) :: gs 
    else 
     before ::: (e :: after.head) :: after.tail 
    } 
    // now a simple foldLeft adding each element to the appropriate list 
    xs.foldLeft(Nil: List[List[A]])(addtoGroup) 
} 

우리가 중복 요소 목록의 목록을 얻을 수 있습니다

List(List((List((346,g), (348,c), (358,a), (361,c)),166), 
      (List((346,g), (348,t), (358,a), (361,c)),178)), 
    List((List((346,a), (348,c), (358,g), (361,g)),34), 
      (List((336,g), (346,a), (348,c), (358,g)),30)), 
    List((List((336,a), (346,g), (348,c), (358,a)),154), 
      (List((336,a), (346,g), (348,t), (358,a)),168)), 
    List((List((328,c), (336,g), (346,a), (348,c)),28), 
      (List((306,c), (328,c), (336,g), (346,a)),4), 
      (List((306,g), (328,c), (336,g), (346,a)),22)), 
    List((List((328,g), (336,a), (346,g), (348,c)),161), 
      (List((328,g), (336,a), (346,g), (348,t)),164), 
      (List((306,c), (328,g), (336,a), (346,g)),282))) 

다음 중첩 된 튜플 목록을 병합하는 함수를 작성합니다.

def merge(ys: List[(List[(Int, String)], Int)]) = 
    ys.foldLeft((Nil:List[(Int, String)], 0)) 
    {(acc, e) => ((acc._1 ++ (e._1 diff acc._1)).sorted, acc._2 + e._2)} 

(누적 된 결과에 아직없는 튜플을 추가하여 튜플을 결합하고 int를 더합니다. .sorted 시각적 결과)

그런 다음

ms.map(merge) 

이주기 중복 항목을 병합을 검토하기 쉽도록하기 위해 단지입니다,하지만 당신은 출력되지 않습니다?

List((List((346,g), (348,c), (348, t), (358,a), (361,c)),344), 
    (List((336,g), (346,a), (348,c), (358,g), (361, g)),64), 
    (List((336,a), (346,g), (348,c), (348,t), (358,a)),322), 
    (List((306,c), (306,g), (328,c), (336,g), (346,a), (348,c)),54), 
    (List((306,c), (328,g), (336,a), (346,g), (348,c), (348,t)),607)) 

편집 : 다음은 업데이트 된 isOverlap입니다. 그러나, 최종 병합 된 출력의 원본, 그래서 더 많은 요소보다 중복을 의미한다, 그래서 그것은 여전히 ​​옳지 않아 :

def isOverlap(a:(List[(Int, String)],Int),b:(List[(Int, String)],Int)) = 
    // combine the tuples by Int, and check that we don't get two entries 
    // for any Int (i.e. if we do, they have different Strings so it's not an overlap) 
!((a._1++b._1).groupBy(_._2).exists(_._2.length > 1)) && 
    // check there are at least 2 matching tuples 
    (a._1 intersect b._1).size >= 3 
+0

답장을 보내 주셔서 감사합니다. 문제가 있습니다. 오류가 내 측면에 있습니다. 죄송합니다. 설명에 하나의 조건이 없습니다. 병합 할 때 튜플의 목록은 최소 3 중첩을 가져야하지만 차이는 없습니다. 즉, 출력에서 ​​첫 번째 튜플 목록은 '(348, c), (348, t)'입니다.나는 – Balaram26

+0

의 질문을 업데이트 할 예정이다. 죄송합니다. 거기에 무엇을 의미하는지 명확하지 않습니다. ( –

+0

두 개의 튜플이 합쳐지면 두 조건 -1입니다. 설명에 주어진대로 3 개 이상의 교차점이 있어야합니다. 2. 두리스트 중 하나의 튜플이 같은 정수이지만 값과 다른 문자열/문자를 가진다면 함께 그룹화 될 수 없습니다 .. – Balaram26