2011-09-12 27 views
5

2d dizisi türü bir boole (önemli değil) var İşlevsel olmayan bir tarzda dizi üzerinde yinelemek kolaydır. FP stili nasıl yapılır?2d scala dizisi yineleme

var matrix = Array.ofDim[Boolean](5, 5) 

eski için ben belirli bir sütun için tüm satırları arasında yineleme ve belirli bir işlev eşleşecektir int listesini dönmek istiyorum. Örnek: sütun 3 için, (4, 3), (5, 3) numaralı hücrede bir özel işlevle eşleşiyorsa, 4, 5 değerini döndürmek için satır 1'den 5'e kadar yineleyin.

def getChildren(nodeId: Int) : List[Int] = { 
    info("getChildren("+nodeId+")") 

    var list = List[Int]() 
    val nodeIndex = id2indexMap(nodeId) 

    for (rowIndex <- 0 until matrix.size) { 
     val elem = matrix(rowIndex)(nodeIndex) 
     if (elem) { 
     println("Row Index = " + rowIndex) 
     list = rowIndex :: list 
     } 
    } 

    list 
    } 

cevap

4

Ne predicate sizin fonksiyonudur

(1 to 5) filter {i => predicate(matrix(i)(3))} 

hakkında fazla Thx v? (5,5) endekslerine başlatıldı

Not 0'dan 4.

Güncelleme gider: İstersen örnek

def getChildren(nodeId: Int) : List[Int] = { 
    info("getChildren("+nodeId+")") 
    val nodeIndex = id2indexMap(nodeId) 

    val result = (0 until matrix.size).filter(matrix(_)(nodeIndex)).toList 
    result.forEach(println) 
    result 
} 

dayalı Sen fiter içinde baskı hareket edebilir Eğer tam olarak örnek

+0

İlk yapının 2d dizisi ise sol dizinin bir dizi döndüreceğini düşünüyorum. – jts

+0

Ah, başka bir fark, doğrudan 2d dizisinde filtrelemeyi düşünüyordum, ancak bunu yaparak satır dizisini kaybediyorum: val children = matrix.filtre (row => row (nodeIndex)) 2 1d dizileri döndürür - ama hangisini bilmiyorum, hangisini bilmiyorum – jts

+0

Gerçekten, yapıyorum yapıyorum bir dizi, bir dizi değil çıktı). Sonuç türü bir IndexedSeq [Int], ve bir Vector olur. Sadece bir Liste istiyorsanız, ancak yapın. Ancak, Vektör genellikle Liste'den daha iyi bir yapıdır. –

1
def findIndices[A](aa: Array[Array[A]], pred: A => Boolean): Array[Array[Int]] = 
    aa.map(row => 
    row.zipWithIndex.collect{ 
     case (v,i) if pred(v) => i 
    } 
) 

sen biraz daha çıkararak daha güzel olmasını planı ayrı olarak bunu istiyorum, çok ve listeyi ters Yalnızca tek bir satırda endekslerini bulur işlevi: filtreler ve üstten fermuarlı rahat değilsen

def findIndices2[A](xs: Array[A], pred: A => Boolean): Array[Int] = 
    xs.zipWithIndex.collect{ 
    case (v,i) if pred(v) => i 
    } 

Ve sonra sopa ile,

matrix.map(row => findIndices2(row, pred)) 
2

yazmaktan başka kullanım-anlama için daha işlevsel bir şekilde:

for { 
    rowIndex <- matrix.indices 
    if matrix(rowIndex)(nodeIndex) 
} yield { 
    println("Row Index = " + rowIndex) 
    rowIndex 
} 

yield için-kavrama sonuçlarından yeni bir koleksiyon oluşturur ve bu nedenle bu ifade iade etmek istediğiniz koleksiyonuna değerlendirir . seq.indices, 0 until seq.size'a eşdeğer bir yöntemdir. küme parantezleri Eğer noktalı virgül olmadan birden fazla satıra izin, ancak isterseniz size in-line bunu yapabilir:

for (rowIndex <- matrix.indices; if matrix(rowIndex)(nodeIndex)) yield rowIndex 

muhtemelen ayrıca bir Array yineleme ediyoruz normalde eğer gerekmez bahsetmeliyiz Endekslere atıfta bulunmak. Eğer normalde ile ilgilidir edilmemelidir öğelerin indeksleri gerektirdiğini Sen

for { 
    row <- matrix 
    elem <- row 
} yield f(elem) 

ancak kullanım-case biraz sıradışı gibi bir şey yapacağını (dizi indeksleri kullanılarak esasen hızlı ve Bir veri elemanını bir sayı ile eşleştirmek için kirli hack). Konum kavramını yakalamak ve kullanmak isterseniz, Map[Int, Boolean] veya case class kullanarak böyle bir alanla daha iyi olabilirsiniz.