2011-01-28 7 views
66

어떤 아이디어가 ????이어야합니까? 내장되어 있습니까? 이 작업을 수행하는 가장 좋은 방법은 무엇입니까?벡터에서 항목의 색인을 찾으려면 어떻게합니까?

(def v ["one" "two" "three" "two"]) 

(defn find-thing [ thing vectr ] 
    (????)) 

(find-thing "two" v) ; ? maybe 1, maybe '(1,3), actually probably a lazy-seq 
+0

브라이언 (Brian 's)이 분명히이 질문에 대한 답변이지만 아래에 cgrand와 Alex Stoddard가 내가 물어 봐야 할 질문에 대답하려고합니다. –

+0

다른 질문에서 올바른 질문을하는 것을 멈추게하는 것은 아무것도 없습니다. –

답변

107

내장 :

user> (def v ["one" "two" "three" "two"]) 
#'user/v 
user> (.indexOf v "two") 
1 
user> (.indexOf v "foo") 
-1 

모든 경기에 대한 지수의 게으른 서열하려면 다음

user> (map-indexed vector v) 
([0 "one"] [1 "two"] [2 "three"] [3 "two"]) 
user> (filter #(= "two" (second %)) *1) 
([1 "two"] [3 "two"]) 
user> (map first *1) 
(1 3) 
user> (map first 
      (filter #(= (second %) "two") 
        (map-indexed vector v))) 
(1 3) 
+1

달콤한, 고마워요. Brian, 내 doc-searcher가 indexOf를 찾지 못했습니다. 아마 Java 일 것입니다. 나는 그것에 종사해야한다. –

+1

@ 존 : 네. indexOf 앞의 점은 Java interop을 나타냅니다. java.lang.String의 'indexOf'메소드를 호출합니다. java.lang은 기본적으로 가져 오기됩니다. 더 많은 예제는 http : // clojure를 참조하십시오.org/java_interop – dermatthias

+19

그것은 String이 아닌, 호출되는 벡터의'indexOf' 메쏘드입니다 :'# public int clojure.lang.APersistentVector.indexOf (java.lang.Object)>' – vemv

3

난 내 자신의 질문에 대답을 시도했지만 브라이언의 비트를 더 나은 대답으로 나에게 그것을!

(defn indices-of [f coll] 
    (keep-indexed #(if (f %2) %1 nil) coll)) 

(defn first-index-of [f coll] 
    (first (indices-of f coll))) 

(defn find-thing [value coll] 
    (first-index-of #(= % value) coll)) 

(find-thing "two" ["one" "two" "three" "two"]) ; 1 
(find-thing "two" '("one" "two" "three")) ; 1 

;; these answers are a bit silly 
(find-thing "two" #{"one" "two" "three"}) ; 1 
(find-thing "two" {"one" "two" "two" "three"}) ; nil 
35

스튜어트 Halloway이 게시물 http://www.mail-archive.com/[email protected]/msg34159.html에 정말 좋은 대답을 주었다. 첫 번째 값을 잡아하려면

(use '[clojure.contrib.seq :only (positions)]) 
(def v ["one" "two" "three" "two"]) 
(positions #{"two"} v) ; -> (1 3) 

단지 결과에 first를 사용합니다.

(first (positions #{"two"} v)) ; -> 1 

편집 : clojure.contrib.seq 내가 간단한 구현 예제와 함께 내 대답을 업데이트 사라졌다 때문에 :

(defn positions 
    [pred coll] 
    (keep-indexed (fn [idx x] 
        (when (pred x) 
        idx)) 
       coll)) 
+0

Very nice! 이것은 제가 예상했던 대답과 같습니다. –

+2

이 답변의 장점에 영향을주지는 않지만 seq-utils는 이제 clojure.contrib.seq로 변경되었습니다. –

+1

@ 존, 사실, 나는 그것을 고쳤다. 감사! – ponzao

23
(defn find-thing [needle haystack] 
    (keep-indexed #(when (= %2 needle) %1) haystack)) 

하지만 인덱스 손보는에 대해 경고를하고 싶습니다 : 가장 자주 보다 적게 관용적이고 어색한 Clojure를 만들어 낼 것입니다.

+0

오, 좋은 '때! 나는 일반적으로 인덱스에 대해서는 동의하지만 CSV 파일이 있고 필드 이름이 헤더에 있고 각 행에서 "필드"필드를 가져 오려고합니다. 그래서 내가하는 일은 "필드"를 찾고 있습니다. 헤더에 다음 행을 nthing. 나는 인터리브와 관련된 이상한 것들을 생각할 수 있지만 읽을 수있는 명시적인 인덱스를 사용하지 않는 좋은 방법이 있습니까? –

+8

유스 케이스 - csv 헤더가있을 때 - (고유 한 열 머리글을 가정 할 때) 조회를 수행 할 맵을 방금 작성했습니다. map _is_은 my lookup을 수행하는 함수이다. ([header-index (zipmap header-vector (iterate inc 0))] ...) –

+0

와우. 당신은 내가 물어 봐야 할 질문에 대답했습니다! –

2

나는 최근에 인덱스를 여러 번 찾아야 만 했었습니다. 문제를 접근하는 다른 방법을 찾는 것보다 쉬웠 기 때문에 제가 선택했습니다. 길을 따라 나는 Clojure 목록에 .indexOf (Object object, int start) 메소드가 없다는 것을 발견했다. clojure.contrib.seq/positions위한 http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

출처 : 그래서 같은 문제를 다루었가 테이너를 누락으로 Clojure의 1.4 clojure.contrib.seq의로서는

(defn index-of 
"Returns the index of item. If start is given indexes prior to 
start are skipped." 
([coll item] (.indexOf coll item)) 
([coll item start] 
    (let [unadjusted-index (.indexOf (drop start coll) item)] 
    (if (= -1 unadjusted-index) 
    unadjusted-index 
    (+ unadjusted-index start))))) 
13

(따라서 positions 함수)를 사용할 수없는 그리고 그것의 종속 clojure.contrib.seq/indexed입니다 : 여기에 사용 가능한

(defn indexed 
    "Returns a lazy sequence of [index, item] pairs, where items come 
    from 's' and indexes count up from zero. 

    (indexed '(a b c d)) => ([0 a] [1 b] [2 c] [3 d])" 
    [s] 
    (map vector (iterate inc 0) s)) 

(defn positions 
    "Returns a lazy sequence containing the positions at which pred 
    is true for items in coll." 
    [pred coll] 
    (for [[idx elt] (indexed coll) :when (pred elt)] idx)) 

(positions #{2} [1 2 3 4 1 2 3 4]) => (1 5) 

: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/positions

+2

이 버전을 게시 해 주셔서 감사합니다. 1.2 이후로 단순 (범위)로 대체 (iterate inc 0) 할 수도 있습니다. – dribnet

2

여기에 loop 구조를 사용하고 실패시 nil을 반환하는 나의 공헌입니다.

나는 할 수있을 때 루프를 피하려고하지만이 문제에 적합하다고 보입니다.

(defn index-of [xs x] 
    (loop [a (first xs) 
     r (rest xs) 
     i 0] 
    (cond 
     (= a x) i 
     (empty? r) nil 
     :else  (recur (first r) (rest r) (inc i))))) 
관련 문제