I like retronym's drop(n).headOption
pattern as it accounts for when you have less children than n
. But I think you meant the second child node (excluding text nodes), not the second instance of the <foo>
tag. With that in mind, combining with your answer or using partialMap
:
node.child.partialMap{case x:scala.xml.Elem => x}.drop(n).headOption
node.child.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).headOption
This has to assume that you won't want to extract text in:
val node = <something><foo/>text</something>
Efficiency wise, the only other thing I could think of is to make filter lazy if you wanted to retrieve the second child when there are a large number of children. I think this may be achieved by running filter on node.child.iterator
instead.
Edit:
Changed toIterable
to iterator
.
good point, calling drop(n)
on an ArrayBuffer
will cause additional allocations, also how many is hard to tell, since it seems drop
is overridden in IndexSeqLike
. But using the iterator would address that too. So for large number of children:
node.child.iterator.filter(_.isInstanceOf[scala.xml.Elem]).drop(n).next
If you want to have it be safe, you may need to define a function to check for hasNext
.
All of this is tested only in 2.8.