2d итерация массива scala - PullRequest
       2

2d итерация массива scala

5 голосов
/ 12 сентября 2011

У меня есть 2d массив типа boolean (не важно). Легко перебирать массив в нефункциональном стиле.Как это сделать в стиле FP?

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

Например, я хотел бы перебрать все строки для данного столбца и вернуть список int, который будет соответствовать конкретной функции.Пример: для столбца 3 итерация по строкам с 1 по 5 для возврата 4, 5, если ячейка в (4, 3), (5, 3) соответствует определенной функции.Thx V много

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
  }

Ответы [ 3 ]

4 голосов
/ 12 сентября 2011

А как же

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

где predicate ваша функция?

Обратите внимание, что инициализация с (5,5) индексами идет от 0 до 4.

Обновление : на основе вашего примера

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
}

Вы можете переместить отпечаток в установщик, если хотите, и перевернуть список, если хотите, точно так же, как в вашем примере

2 голосов
/ 12 сентября 2011

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

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

yield создает новую коллекцию из результатовдля понимания, поэтому это выражение оценивает коллекцию, которую вы хотите вернуть.seq.indices - это метод, эквивалентный 0 until seq.size.С помощью фигурных скобок вы можете разделить несколько строк без точек с запятой, но вы можете сделать это в строке, если хотите:

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

Следует, вероятно, также упомянуть об этом, как правило, если вы перебираете массив, который вы выиграли 'Не нужно ссылаться на индексы вообще.Вы бы сделали что-то вроде

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

, но ваш вариант использования немного необычен в том смысле, что он требует индексов элементов, с которыми вам обычно не следует беспокоиться (использование индексов массива по сутибыстрый и грязный хак для сопряжения элемента данных с номером).Если вы хотите захватить и использовать понятие положения, вам лучше использовать Map[Int, Boolean] или case class с таким полем.

1 голос
/ 12 сентября 2011
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 
  }
)

Вы можете сделать рефакторинг, чтобы сделать его немного лучше, выделив функцию, которая находит индексы только в одной строке:

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

А потом напиши

matrix.map(row  => findIndices2(row, pred))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...