2011-01-12 9 views
9

이것은 내가 해결 한 문제입니다. 그러나 모든 필수 스칼라 놈입니다. 완전히 우아하지 않은 것을 발견했습니다. 개선에 대한 아이디어는 높이 평가됩니다.특정 위치의 목록에 스칼라 삽입

val l1 = 4 :: 1 :: 2 :: 3 :: 4 :: Nil // original list 
val insert = List(88,99) // list I want to insert on certain places 

// method that finds all indexes of a particular element in a particular list 
def indexesOf(element:Any, inList:List[Any]) = { 
     var indexes = List[Int]() 
     for(i <- 0 until inList.length) { 
       if(inList(i) == element) indexes = indexes :+ i 
     } 
     indexes 
} 


var indexes = indexesOf(4, l1) // get indexes where 4 appears in the original list 

println(indexes) 

var result = List[Any]() 

// iterate through indexes and insert in front 
for(i <- 0 until indexes.length) { 
     var prev = if(i == 0) 0 else indexes(i-1) 
     result = result ::: l1.slice(prev, indexes(i)) ::: insert 
} 
result = result ::: l1.drop(indexes.last) // append the last bit from original list 

println(result) 

나는 더 우아한 해결책이 이와 같은 것으로 달성 될 수 있다고 생각했지만, 그것은 순수한 추측 일뿐입니다.

var final:List[Any] = (0 /: indexes) {(final, i) => final ::: ins ::: l1.slice(i, indexes(i)) 

답변

14
def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = { 
    xs.map(x => if (p(x)) extra ::: List(x) else List(x)).flatten 
} 

scala> insert(List(4,1,2,3,4),List(88,99)){_ == 4} 
res3: List[Int] = List(88, 99, 4, 1, 2, 3, 88, 99, 4) 

편집 : 설명했다. 한 가지 x 후 그들 중 많은 복수 xs해야합니다 것처럼 여기

우리의 목표는 여기 --commonly 목록에 사용 xs라는 또 다른 목록 (선택 요소의 앞 (extra이라고 함) 목록을 삽입하는 것입니다). 우리는이 유형이 우리가 가질 수있는 모든 유형의 목록에서 작업하기를 원하므로 generic 형식 [A]으로 주석을 추가합니다.

삽입 할 요소는 무엇입니까? 함수를 작성할 때 알지 못하기 때문에 각 요소에 대해 true 또는 false라는 함수를 제공합니다 (p: A => Boolean).

이제 목록 x의 각 요소에 대해 삽입을해야합니까? 즉, p(x)이 참인지 확인합니다. 예인 경우 우리는 단지 그것을 빌드합니다 : extra ::: List(x)extra의 요소이고 그 뒤에 단일 항목 x이옵니다. (이 경우는 extra :+ x으로 작성하는 것이 좋습니다. 끝에 하나의 항목을 추가하십시오.) 아니요, 하나의 항목 만 있지만 모든 유형이 동일하기를 원하기 때문에 List(x) 대신 x으로 지정합니다. 그래서 지금, 경우에 우리가

4 1 2 3 4 

같은 것을 가지고 우리의 조건이 우리가 5 64 전에 삽입하는 것입니다, 우리는 우리가리스트의 목록을 제외하고는이, 우리가 원하는 것을 정확히

List(5 6 4) List(1) List(2) List(3) List(5 6 4) 

를 생성합니다. 내부 목록을 없애고 모든 것을 단일 목록으로 평탄화하려면 flatten으로 전화하면됩니다.

+0

작품 : 첫 번째 [A]는 무엇을 의미합니까? 무슨 뜻이야? – Murgh

+0

첫 번째'[A]'는 일반적인 방법이라는 것을 의미합니다 (어떤 유형은'A'에서 작동하고, 나중에 나오는'A '는 같은 것을 참조하고 있습니다). '_'은 "변수가 무엇이든간에"을 의미합니다. 그것은'x => x == 4'에 대한 지름길입니다. –

+2

'xs.map (..). flatten'은'xs.flatMap (..)'으로 쓰여질 수 있습니다. – Landei

10

평평한 트릭이 귀엽다. 나는 여기 map을 직접 사용하지 않을 것이다. 내 관점에서 볼 때이 문제는 목록을 살펴보고 "수집"(결과 목록)하기를 원하는 폴드 (fold)의 일반적인 응용 프로그램입니다. 우리는 거꾸로 우리의 결과 목록을 원하지 않기 때문에, foldRight (일명, :\는) 여기에 올바른 버전 :

def insert[A](xs: List[A], extra: List[A])(p: A => Boolean) = 
    xs.foldRight(List[A]())((x,xs) => if (p(x)) extra ::: (x :: xs) else x :: xs) 
3

는 여기에 실제 삽입을 처리 할 수 ​​Seq#patch를 사용하여, 또 다른 가능성이다. foldRight를 사용하여 이후의 인덱스가 먼저 처리되도록합니다. 삽입은 삽입 후 모든 요소의 인덱스를 수정하므로 다른 경우 까다로울 수 있습니다.

def insert[A](xs: Seq[A], ys: Seq[A])(pred: A => Boolean) = { 
    val positions = xs.zipWithIndex filter(x => pred(x._1)) map(_._2) 
    positions.foldRight(xs) { (pos, xs) => xs patch (pos, ys, 0) } 
} 
관련 문제