2014-09-02 4 views
5
val data = List("foo", "bar", "bash") 
val selection = List(0, 2) 
val selectedData = data.filter(datum => selection.contains(datum.MYINDEX)) 
//             INVALID CODE HERE^
// selectedData: List("foo", "bash") 

내가 선택한 인덱스 목록이 표시된 List을 필터링하고 싶습니다. filter 메서드에서 목록 항목의 인덱스를 참조 할 수 있다면 위와 같이 해결할 수 있지만 위의 경우 datum.MYINDEX은 유효하지 않습니다.항목 목록으로 필터를 필터링 하시겠습니까?

어떻게 대신이 작업을 수행 할 수 있습니까?

답변

6

zipWithIndex을 사용하여 항목 색인에 대한 참조를 유지하고 필터링하여 색인을 멀리 매핑하는 방법은 어떻습니까?

data.zipWithIndex 
    .filter{ case (datum, index) => selection.contains(index) } 
    .map(_._1) 
+0

마지막 링크 (실제로 링크를 읽은 후)는 견적 마이닝입니다. 즉, 브라케팅 논쟁은 나이가 많은 이집트의 대괄호 논쟁이었습니다. 자바와 같은 언어는 선택적 요소입니다 (스칼라에서는 그렇지 않습니다). 이제 저는 여는 괄호와 같은 줄 *에 성명/표현을 넣을 수있는 언어가 무엇인지 알지 못합니다. 그것은 객관적으로 잘못된 것이지 개인적인 취향이 아닙니다. – samthebest

+0

내가 인정한 유일한 사실은이 안내서와 중괄호 문제 이전의 공간에 대해 조금 암묵적이며, 닫는 중괄호는 그 자체의 줄에 있어야한다는 것만 명시합니다. ".. 닫는 중괄호는 바로 다음 행에 있습니다 함수의 마지막 줄 "을 참조하십시오. 그러므로 스타일 가이드의 명시적이고 객관적으로 사실 인 부분에 따라 마지막으로 편집하고 모든 암시적인 실수를 여러분에게 맡깁니다. – samthebest

+0

@samthebest, 다른 서식 지정 도구 및 설정이 많이 있습니다. 왜 당신은 특정 것을 사용하라고 주장합니까? – Basilevs

0
내 마음에 온

첫 번째 솔루션은 쌍 (요소, 인덱스)의 목록을 작성 선택 인덱스, 다음 순서대로 목록을 결과 맵은 원시 elementd를 유지하는 것을 포함하는 경우 확인하여 모든 요소를 ​​필터링 할 수 있었다 (색인 생략).

data.zipWithIndex.filter(pair => selection.contains(pair._2)).map(_._1) 

또는 더 읽기 : 코드는 자기 설명이다.

val elemsWithIndices = data.zipWithIndex 
val filteredPairs = elemsWithIndices.filter(pair => selection.contains(pair._2)) 
val selectedElements = filteredPairs.map(_._1) 
+0

아마도 2 일은 스칼라 경험 2 일과 같이 누군가에게 더 읽기 쉽지만, 첫 번째 방법은 스칼라가 가장 선호하는 스타일이므로 그 우아함을 선호합니다. – samthebest

1

인덱싱 속도가 느린 것처럼이 목록에 (비록 잠재적으로 느린에 대해 그것을 다른 방법을 수행하는 깔끔한이다 (O (N)) 벡터 당신이 지표을 벌써의 목록을 가지고 있기 때문에 더 좋을 것이다. 반면에, data의 모든 항목에 대한 다른 솔루션의 contains는)

val data = List("foo", "bar", "bash") 
     //> data : List[String] = List(foo, bar, bash) 
val selection = List(0, 2) 
     //> selection : List[Int] = List(0, 2) 
selection.map(index=>data(index)) 
     //> res0: List[String] = List(foo, bash) 
+0

'data'리스트의 크기보다 큰 인덱스를 가지고 있다면 이것은 예외를 던질 것입니다. –

+0

예. OP는 그것이 문제인지 여부와 잘못된 색인에 대해 어떤 행동을해야 하는지를 말할 수 있습니다. –

+0

예외를 던져 넣는 것은 일반적으로 좋지 않습니다. –

0

정확히 빠르지 심지어

val data = List("foo", "bar", "bash") 
val selection = List(0, 2) 
val selectedData = selection.map(index => data(index)) 

나 : y를, 가장 효율적인 방법은 직접 그 인덱스 선택하는 것입니다

val selectedData = selection.sorted.map(data) 
:

val selectedData = selection.map(data) 

하거나 데이터 항목의 순서를 유지해야하는 경우

업데이트

모든 가능성을 찾는 정신으로 전자 알고리즘은, 여기에 사용 된 버전의 collect :

val selectedData = data 
    .zipWithIndex 
    .collect { 
    case (item, index) if selection.contains(index) => item 
    } 
+1

'data'리스트의 크기보다 큰 인덱스를 가지고 있다면 이것은 예외를 던질 것이다. –

+0

그래, 좋은 지적이야. –

+0

하지만 예외가 필요한 동작 일 수 있습니다. 너무 큰 인덱스를 가진 List의 단순한 단일 인덱스를 수행하는 것과 같습니다. –

0

이 작품 :

val data = List("foo", "bar", "bash") 
val selection = List(0, 2) 
val selectedData = data.filter(datum => selection.contains(data.indexOf(datum))) 
println (selectedData) 

출력 : 목록을 할 수있는 (foo는, bash는)

0

는 IS 다음 아마도 가장 확장 성 방법 효율성 측면에서 볼 때, 그리고 SO에 대한 많은 답과 달리 공식 스칼라 스타일 가이드를 정확히 따르고 있습니다.

import scala.collection.immutable.HashSet 

val selectionSet = new HashSet() ++ selection 

data.zipWithIndex.collect { 
    case (datum, index) if selectionSet.contains(index) => datum 
} 

결과 컬렉션 등, 게으른 시퀀스로 data를 권하곤, flatMap, map 추가로 전달 될 경우. 실제로 어쨌든 collect의 경우 zipWithIndex 하나는 2 패스를 피하기 위해이 작업을 수행해야하지만 벤치마킹 된 것이 많으면 의심 스럽습니다.

관련 문제