Мне нравится шаблон drop(n).headOption
ретронима, так как он учитывается, когда у вас меньше детей, чем n
. Но я думаю, что вы имели в виду второй дочерний узел (исключая текстовые узлы), а не второй экземпляр тега <foo>
. Имея это в виду, в сочетании с вашим ответом или используя partialMap
:
node.child.partialMap{case x:scala.xml.Elem => x}.drop(n).headOption
node.child.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).headOption
Это предполагает, что вы не захотите извлекать текст в:
val node = <something><foo/>text</something>
В отношении эффективности, единственное, о чем я мог подумать, это сделать фильтр ленивым, если вы хотите получить второго ребенка, когда есть большое количество детей. Я думаю, что этого можно достичь, запустив фильтр вместо node.child.iterator
.
Edit:
Изменено toIterable
на iterator
.
Хорошо, что вызов drop(n)
для ArrayBuffer
вызовет дополнительные выделения, а также, сколько из них трудно сказать, так как кажется, что drop
переопределено в IndexSeqLike
. Но использование итератора также решит эту проблему. Так что для большого количества детей:
node.child.iterator.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).next
Если вы хотите, чтобы это было безопасно, вам может потребоваться определить функцию для проверки на hasNext
.
Все это проверено только в 2.8.