2010-02-06 24 views

Trả lời

122

Tôi tin rằng bạn đang tìm kiếm zipWithIndex?

scala> val ls = List("Mary", "had", "a", "little", "lamb") 
scala> ls.zipWithIndex.foreach{ case (e, i) => println(i+" "+e) } 
0 Mary 
1 had 
2 a 
3 little 
4 lamb 

Từ: http://www.artima.com/forums/flat.jsp?forum=283&thread=243570

Bạn cũng có biến thể như:

for((e,i) <- List("Mary", "had", "a", "little", "lamb").zipWithIndex) println(i+" "+e) 

hay:

List("Mary", "had", "a", "little", "lamb").zipWithIndex.foreach((t) => println(t._2+" "+t._1)) 
+0

Đây có phải là hiệu quả? – ziggystar

+50

Không. Tôi muốn làm: println ("0 Mary \ n1 có \ n2 a \ n3 ít \ n4 con chiên") –

+2

Vâng, ý tôi là sử dụng phương thức 'zipWithIndex' để lấy chỉ mục bên trong một vòng lặp/bản đồ/. – ziggystar

5

CountedIterator trong 2.7.x (bạn có thể lấy từ trình lặp bình thường có .counted). Tôi tin rằng nó không được chấp nhận (hoặc chỉ đơn giản là gỡ bỏ) trong 2,8, nhưng nó đủ dễ dàng để cuộn của riêng bạn. Bạn cần phải có thể đặt tên cho trình lặp:

val ci = List("These","are","words").elements.counted 
scala> ci map (i => i+"=#"+ci.count) toList 
res0: List[java.lang.String] = List(These=#0,are=#1,words=#2) 
3

Hoặc, giả bộ sưu tập của bạn có thời gian truy cập thường xuyên, bạn có thể lập bản đồ danh sách chỉ mục thay vì bộ sưu tập thực tế:

val ls = List("a","b","c") 
0.until(ls.length).map(i => doStuffWithElem(i,ls(i))) 
+1

Cách thanh lịch hơn để thực hiện điều này đơn giản là: 'ls.indices.map (i => doStuffWithElem (i, ls (i))' –

+3

@aksiksi Vâng, thấy rằng ['chỉ số' được thực thi là' 0 cho đến khi length'] (https://github.com/scala/scala/blob/2.12.x/src/library/scala/collection/SeqLike.scala#L668) khá nhiều điều tương tự: P –

+0

hahaha bạn giành chiến thắng: D –

8

Các giải pháp được đề xuất phải thực tế là chúng tạo ra các bộ sưu tập trung gian hoặc giới thiệu các biến không cần thiết. Cuối cùng, tất cả những gì bạn cần làm là theo dõi số bước lặp lại. Điều này có thể được thực hiện bằng cách sử dụng ghi nhớ. Mã kết quả có thể trông như

myIterable map (doIndexed(someFunction)) 

các doIndexed -Function kết thúc tốt đẹp các chức năng bên trong mà nhận được cả một chỉ số một các yếu tố của myIterable. Điều này có thể quen thuộc với bạn từ JavaScript.

Đây là cách để đạt được mục đích này. Xem xét tiện ích sau:

object TraversableUtil { 
    class IndexMemoizingFunction[A, B](f: (Int, A) => B) extends Function1[A, B] { 
     private var index = 0 
     override def apply(a: A): B = { 
      val ret = f(index, a) 
      index += 1 
      ret 
     } 
    } 

    def doIndexed[A, B](f: (Int, A) => B): A => B = { 
     new IndexMemoizingFunction(f) 
    } 
} 

Đây là tất cả những gì bạn cần. Bạn có thể áp dụng điều này ví dụ như sau:

import TraversableUtil._ 
List('a','b','c').map(doIndexed((i, char) => char + i)) 

mà kết quả trong danh sách

List(97, 99, 101) 

Bằng cách này, bạn có thể sử dụng thông thường traversable chức năng tại các chi phí của gói chức năng hiệu quả của bạn. Chi phí là việc tạo ra đối tượng ghi nhớ và bộ đếm trong đó. Nếu không giải pháp này là tốt (hoặc xấu) về bộ nhớ hoặc hiệu suất như sử dụng unindexed map. Thưởng thức!

+1

Đây là một giải pháp rất thanh lịch cho vấn đề này +1 cho việc không tạo ra một bộ sưu tập tạm thời. t làm việc trong một bộ sưu tập song song, nhưng vẫn là một giải pháp rất tốt đẹp. – fbl

+3

Nếu bạn không muốn tạo một bộ sưu tập tạm thời, chỉ cần sử dụng 'coll.view.zipWithIndex' thay vì' coll.zipWithIndex' – tsuna

33

Sử dụng. bản đồ in. zipWithIndex

val myList = List("a", "b", "c") 

myList.zipWithIndex.map { case (element, index) => 
    println(element, index) 
    s"${element}(${index})" 
} 

Kết quả:

List("a(0)", "b(1)", "c(2)") 
+4

Đây là ví dụ đầu tiên tôi đã thấy sử dụng một 'bản đồ' theo yêu cầu thay vì chỉ cần in bên trong 'foreach'. –

Các vấn đề liên quan