1

I'm parsing excel file and I'm trying to find an index for "IP" column. The code below will actually give me the index, but return value type for that 'let' is Any.

Is there a prettier way to get data from iterator if the data matches with if statement?

val ipColumn = headerRow.cellIterator().let {
    it.forEach { cell ->  
        if ("IP" == formater.formatCellValue(cell))
            return@let cell.columnIndex 
    }
}
zsmb13
  • 85,752
  • 11
  • 221
  • 226
rooste
  • 160
  • 9

3 Answers3

2

I assume you're using Apache POI library, where cellIterator is a method returning an Iterator<Cell>. In such a case, you could do something like this:

val ipColumn: Int? = headerRow.cellIterator()
    .asSequence()
    .firstOrNull {
        "IP" == formatter.formatCellValue(it)
    }
    ?.columnIndex

Please note I didn't test the code, so it might even contain compilation issues, but I hope it gives you a hint

user2340612
  • 10,053
  • 4
  • 41
  • 66
1

Using List or Sequence

Your best bet would be converting the iterator to Sequence, where you can call the find() method.

val index = headerRow
    .asSequence() //To sequence
    .find { "IP" == formater.formatCellValue(it) }

Using Iterator

If for some kind of reason you can't use List I don't really think there is a prettier way (of course there always can be). But if your main problem is that you get a type of Any from your let construction you can always just cast the found index with as Int or if you are not sure that the index will be of type Int, use as? Int, which will return nullable value of Int:

val ipColumn = headerRow.cellIterator().let {
it.forEach { cell ->  
    if ("IP" == formater.formatCellValue(cell))
        return@let cell.columnIndex 
    }
} as Int //This returns `Int`

Using extensions

If you still don't like any of those 2 options. Or if you want to use the code in more places. You can create yourself an extension function/method:

fun Row.find(predicate: (Cell) -> Boolean): Cell? 
    = cellIterator().asSequence().find(predicate) //Put this code anywhere is your code...

After you put these lines anywhere in your code, you can simply call:

val index = headerRow
    .find { "IP" == formater.formatCellValue(it) }?
    .columnIndex //This returns optional Int

Please note, that I did not compile any of these examples, I do not have the necessary library for that!

Samuel Kodytek
  • 1,004
  • 2
  • 11
  • 23
1

Not from an Iterator directly, but it can be converted to a Sequence. Of course, usually you'll have an Iterable and be able to call find and so on directly, maybe in this case too depending on type of headerRow:

headerRow.cellIterator().asSequence().
    find { cell -> "IP" == formater.formatCellValue(cell) }?.
    columnIndex

?. in the end handles the case where find returned null because there's no suitable column.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487