takeWhile, который включает фактическое значение, соответствующее предикату (takeWhileInclusive) - PullRequest
1 голос
/ 09 мая 2019

Часто я вижу проблему в том, что я хочу собирать значения из списка, пока значение не совпадет, но там, где мне также нужно само соответствующее значение.Хотя takeWhile почти идеально подходит для этого вопроса, на самом деле он не позволяет сохранить последнюю (или в основном совпадающую) запись.

Простой пример: показать иерархию классовОбъект до первого класса, который реализует определенный интерфейс

generateSequence(obj::class.java, Class<*>::getSuperclass)
        .takeWhile { interestedType !in it.interfaces }
        .joinToString(" > ")
        .run(::println)

для obj=arrayListOf(1) и interestedType=Collection::class.java Я хочу увидеть что-то вроде:

class java.util.ArrayList > class java.util.AbstractList > class java.util.AbstractCollection

, и я надеялся, что это будеттак же просто, как:

generateSequence(obj::class.java, Class<*>::getSuperclass)
        .takeWhileInclusive { interestedType !in it.interfaces }
        .joinToString(" > ")
        .run(::println)

Но такой функции не существует (пока?).Но, может быть, есть какая-то другая функция, которая действительно близка к этому?Или, может быть, не более двух последовательных вызовов функций уже легко реализуемы, а я просто не вижу этого?

Чего я не ищу: как мне решить эту конкретную проблему, касающуюся того, какой класс в иерархии реализуетинтерфейс.Это простой пример.То, что я также не ищу: как я могу реализовать это с помощью Iterator или базового цикла while / for ... (за исключением: если он легко читается и не занимает больше 3 строк, тогда ...Возможно; -)).

Что я нашел: Безопасна ли эта реализация takeWhileInclusive? , которая также связывает свою собственную реализацию (и ее вдохновение) для takeWhileInclusive.Однако мне не очень нравится, что он использует var, чтобы зарегистрировать, нашел ли он совпадение ... Я также немного не уверен, когда читаю комментарии («предполагаю последовательный порядок»), действительно ли эта реализация имеет смысл / действительнобезопасно.

1 Ответ

2 голосов
/ 09 мая 2019

Я еще не нашел подходящей существующей функции, и мне также не очень нравится связанное решение, поэтому я немного поиграл и получил следующую функцию расширения:

fun <T> Sequence<T>.takeWhileInclusive(predicate: (T) -> Boolean) = sequence {
    with(iterator()) {
        while (hasNext()) {
            val next = next()
            yield(next)
            if (!predicate(next)) break
        }
    }
}

Используется sequence, ленивые значения при необходимости. По крайней мере, я могу опустить промежуточный var и предположить, что это может быть более полезным в этом случае ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...