it-swarm.com.ru

В Scala, как я могу найти размер элемента массива

Scala новичок, есть массив, где один элемент является массивом:

val aaa = Array("a", "b", Array(1, 2, 3), "c")

Это работает:

In []: aaa(2)
Out[]: Array(1, 2, 3)

Это работает

In []: Array(1, 2, 3).size
Out[]:3

Это не:

In []: aaa(2).size
Out[]:
Name: Compile Error
Message: <console>:15: error: value size is not a member of                     
Java.io.Serializable
          aaa(2).size
                 ^

Что я делаю не так? Thnaks 

6
Ezer K

Когда вы создаете массив, используя следующий литерал 

val aaa = Array("a", "b", Array(1, 2, 3), "c")

Поскольку тип элементов различен, тип массива aaa создается с помощью Java.io.Serializable

aaa: Array[Java.io.Serializable] = Array(a, b, Array(1, 2, 3), c)

Поэтому, когда вы возвращаетесь ко второму элементу, тип ссылки будет иметь значение Serializable, и в нем нет свойства size. Таким образом, нам нужно экспортировать typecast/преобразовать 2-й элемент в Array, используя asInstanceOf . Как показано ниже

 if (aaa(2).isInstanceOf[Array[Int]]) 
       aaa(2).asInstanceOf[Array[Int]].size
2
rajuGT

Наиболее распространенный тип для вашего объявления - сериализуемый

val aaa = Array("a", "b", Array(1, 2, 3), "c")
Array[Java.io.Serializable] 

Если вы хотите использовать его с размером, вы можете явно определить:

val aaa: Array[Seq[Any]] = Array("a", "b", Array(1, 2, 3), "c")

в этом случае все строки будут преобразованы в последовательности символов.

2
mavarazy

Как упоминалось в комментариях, не рекомендуется смешивать массивы и не-массивы (и вообще элементы разных типов) в массиве. Иногда бывают угловые случаи, когда вы не можете обойтись без этого, но, как правило, массивы (и другие контейнеры scala) предназначены для хранения однородных типов. 

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

val (arrays, nonArrays) =  
  Array("a", "b", Array(1, 2, 3), "c").partition { 
     case a: Array[_] => true
     case _ => false
  }

Теперь вы можете легко определить длину всех ваших массивов:

  arrays.foreach { println(_.size) }

Если вы хотите сохранить исходную информацию о положении, вы можете сначала сжать исходный массив индексами:

 val (arrays, nonArrays) = Array("a", "b", Array(1, 2, 3), "c")
   .zipWithIndex
   .partition {
      case (a: Array[_], _) => true
      case _ => false
   }

 arrays.foreach { 
   case (array, index) => 
     prinlnt(s"Array length at index $index is ${array.size}")
 }
1
Dima