Вернуться / вырваться из бесконечного foreach в kotlin - PullRequest
0 голосов
/ 12 декабря 2018

Для класса я должен сделать программу, которая вычисляет задачу на день рождения. Теперь я пытаюсь изучать kotlin одновременно, и у меня возникают проблемы с небольшим фрагментом кода:

        val checkSet = mutableSetOf<Int>()
        generateSequence{ Random.nextInt(n)}.forEach {
            if(!checkSet.add(it)) {
                return@outForeach
            }
        }
        outForeach@
        sum += checkSet.size

Как видите, я пытаюсь сделать это с бесконечной последовательностью.Kotlin не принимает это как outForeach - неразрешенная ссылка.Но это тоже не работает:

        val checkSet = mutableSetOf<Int>()
        generateSequence{ Random.nextInt(n)}.forEach {
            if(!checkSet.add(it)) {
                return@forEach
            }
        }
        sum += checkSet.size

Это просто снова запустит цикл forEach.Есть ли способ реализовать что-то как forEachUntil или около того?

ps Я знаю, что это выглядит примерно так: 'return' не выпрыгивает из forEach в Kotlin Просто я действительно не получаю ответы и не знаю, применимо ли это здесь.Также способ реализации forEachUntil кажется мне гораздо более элегантным

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Альтернативы, которые вы можете рассмотреть вместо first:

  • с использованием простого while без тела:

    while (checkSet.add(Random.nextInt(n))); // <- that semicolon is required! otherwise you execute what is coming next within the while
    
  • с использованием run с этикеткой:

    run outForeach@{
      generateSequence{ Random.nextInt(n)}.forEach {
        if(!checkSet.add(it)) {
          return@outForeach
        }
      }
    }
    
  • возможно также takeWhile может быть полезным.В этом конкретном случае, однако, это, безусловно, не так (как это сверяется с checkSet и оставляет нам последовательность, которая не потребляется ... но если условие будет другим, может иметь смысл рассмотреть что-то вроде take, takeWhile, takeLast и т. Д.):

    generateSequence { Random.nextInt(n) }
        .takeWhile(checkSet::add) // as said: for this specific condition it doesn't make sense... 
        .forEach { /* do nothing except consume the sequence */ } // the same values you added to the set would be available in this step of course
    
0 голосов
/ 12 декабря 2018

Я думаю, что нашел решение сам:

        val checkSet = mutableSetOf<Int>()
        generateSequence{ Random.nextInt(n)}.first { !checkSet.add(it) }
        sum += checkSet.size

В основном используйте функцию first () и продолжайте возвращать false, пока не захотите выйти из цикла.И просто сбросьте возврат функции сначала ()

...