벡터에서 항목의 인덱스를 어떻게 찾습니까?


84

어떤 아이디어 ????가 있어야합니까? 내장이 있습니까? 이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

(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

Brian 's가이 질문에 대한 답이지만, 아래에서 cgrand와 Alex Stoddard는 내가 물어봐야 할 질문에 답하기 위해 공모합니다.
John Lawrence Aspden 2011 년

아무것도 :) 별도의 질문에 정확한 질문에서 당신을 중지하지
조나단 벤

답변:


138

내장 :

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)

3
감사합니다. 브라이언, 제 doc-searcher가 indexOf를 찾지 못했습니다. 아마도 Java이기 때문일 것입니다. 나는 그것에 대해 노력해야 할 것입니다.
John Lawrence Aspden 2011 년

2
@John : 네. indexOf 앞의 점은 Java interop을 나타냅니다. java.lang.String에서 'indexOf'메소드를 호출합니다. 기본적으로 java.lang을 가져옵니다. 더 많은 예제를 참조 clojure.org/java_interop
dermatthias

25
indexOf호출되는 것은 String이 아니라 벡터의 메소드입니다.#<Method public int clojure.lang.APersistentVector.indexOf(java.lang.Object)>
vemv

44

Stuart Halloway는이 게시물 http://www.mail-archive.com/clojure@googlegroups.com/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))

아주 좋아요! 이것이 제가 기대했던 대답입니다.
John Lawrence Aspden 2011 년

2
이 답변의 장점에 영향을 미치지는 않지만 seq-utils는 이제 clojure.contrib.seq 만 변경되었습니다.
John Lawrence Aspden 2011 년

1
@John, 사실, 나는 그것을 고쳤다. 감사!
ponzao 2011 년

clojure.contib.seqclojure 1.6에서 어디서 얻을 수 있습니까? 목록에 라이브러리 없음 : dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go
d9k

@ d9k, "여기에 clojure.contrib 네임 스페이스가 나열되어 있지만 마이그레이션 세부 정보가없는 경우 해당 네임 스페이스를 유지하기 위해 자원 한 사람이 없음을 의미합니다." 에 대한 예제 구현을 추가했습니다 positions.
ponzao

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

그러나 나는 당신에게 인덱스를 조작하는 것에 대해 경고하고 싶습니다. 대부분은 덜 관용적이고 어색한 Clojure를 생성 할 것입니다.


오 좋은 '언제'! 일반적으로 색인에 대해 동의하지만 CSV 파일이 있고 필드 이름이 헤더에 있고 각 행에서 "필드"필드를 가져오고 싶습니다. 그래서 내가하는 일은 "필드"를 찾는 것입니다. 헤더에 다음 행에 nthing. 인터리브로 할 수있는 이상한 일을 생각할 수 있지만, 읽을 수있는 명시 적 인덱스를 사용하지 않는 좋은 방법이 있습니까?
John Lawrence Aspden 2011 년

8
유스 케이스 (csv 헤더)가있을 때 방금 조회를 수행하기위한 맵을 구축했습니다 (고유 한 열 헤더 가정). 지도 색인 조회를 수행하는 내 기능입니다. (let [header-index (zipmap header-vector (itrate inc 0))] ...)
Alex Stoddard

1
와. 내가 물어봐야 할 질문에 답하셨습니다!
John Lawrence Aspden 2011 년

3
글쎄, 나는 Alex의 솔루션에 매우 유사한 것을 제안했을 것입니다. (-> "colname"헤더-인덱스 행) 그리고 당신의 가치가 있습니다.
cgrand

14

Clojure 1.4부터 clojure.contrib.seq (따라서 positions함수)는 관리자가 없기 때문에 사용할 수 없습니다 : http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

소스 clojure.contrib.seq/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부터 (반복 inc 0)을 단순히 (범위)로 바꿀 수도 있습니다.
dribnet 2013 년

6

나는 내 질문에 답하려고했지만 Brian은 더 나은 답으로 나를 이겼다!

(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

3

다음은 looping 구조를 사용하고 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)))))

2

최근에 색인을 여러 번 찾아야했거나 문제에 접근하는 다른 방법을 찾는 것보다 쉬웠 기 때문에 선택했습니다. 그 과정에서 Clojure 목록에 .indexOf (Object object, int start) 메서드가 없다는 것을 발견했습니다. 나는 다음과 같이 문제를 처리했습니다.

(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)))))

0

나는 reduce-kv로 갈 것이다.

(defn find-index [pred vec]
  (reduce-kv
    (fn [_ k v]
      (if (pred v)
        (reduced k)))
    nil
    vec))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.