Có bất kỳ danh sách/Trình tự tích hợp nào hoạt động như map
và cung cấp chỉ mục của phần tử không?Tôi có thể sử dụng bản đồ và nhận chỉ mục như thế nào ở Scala?
Trả lời
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))
Có 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)
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)))
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))' –
@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 –
hahaha bạn giành chiến thắng: D –
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!
Đâ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
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
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)")
Đâ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'. –
Đây có phải là hiệu quả? – ziggystar
Không. Tôi muốn làm: println ("0 Mary \ n1 có \ n2 a \ n3 ít \ n4 con chiên") –
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