2015-02-18 3 views
1

Учитывая потенциально большое изображение (или двумерный массив чисел), я хотел бы перебрать все пиксели (или числа) и, например, подсчитайте все черные (или 0 значений).Scala: fold over two-array array

Я знаю, что могу просто использовать для понимания как

for (y <- 0 until img.height; x <- 0 until img.width) { 
    ... 
} 

но мне нужно изменяемый переменную для подсчета. На самом деле это не проблема, но предположим, что я не хочу этого и хотел бы использовать более функциональный стиль, как мне это сделать, не создавая большую структуру данных с элементами высоты ширины x (другими словами, эффективность диапазонов 0 until img.height и 0 until img.width)?

ответ

5

Карта по коллекции, превращая внутренние из них в subcounts, а затем суммировать эти:

scala> val m = Array(
     Array("B","B","W"), 
     Array("W","W","B"), 
     Array("W","W","W") 
     ) 
m: Array[Array[String]] = Array(Array(B, B, W), Array(W, W, B), Array(W, W, W)) 

scala> m.map(_.count(_ == "B")).sum 
res0: Int = 3 

EDIT

Вы можете создать Stream с помощью

Stream.tabulate(img.height, img.width)(identity) 

и затем используйте

stream.count(isBlack) 

Отметьте, что Stream.tabulate принимает до 5 измерений (в качестве первого аргумента).

+0

Просто напомню, что '' abc "==" abc "' не работает. –

+5

@SarveshKumarSingh В Scala он работает. – Kolmar

+0

Ну ... Это конечно ... Новости для меня. –

1

Вы можете использовать для понимания с диапазонами для преобразования изображения в последовательности пикселей:

for { 
    y <- 0 until img.height 
    x <- 0 until img.width 
} yield image(x, y) 

Но это создаст полную последовательность в памяти. Для того, чтобы сделать его ленивым вы можете принять взгляды диапазонов:

for { 
    y <- (0 until img.height).view 
    x <- (0 until img.width).view 
} yield image(x, y) 

С, что вы можете вызывать функции более высокого уровня на этой последовательности, чтобы вычислить, что вам нужно:

(
    for { 
     y <- (0 until img.height).view 
     x <- (0 until img.width).view 
    } yield image(x, y) 
).count(_.isBlack) 

Вы можете, конечно, добавьте это преобразование в последовательность пикселей как неявный метод вашего класса изображения:

implicit class ImageOperations(image: Image) { 
    def toPixelSeq = for { 
     y <- (0 until img.height).view 
     x <- (0 until img.width).view 
    } yield image(x, y) 
} 
+0

Это похоже на то, что я имел в виду с потоками, но представления могут быть лучше, так как я хочу предотвратить мемонирование в любом случае. – herman