R: Как напечатать только первые 5 ИСТИННЫХ условий в цикле, не ограничивая диапазон цикла

#r

Вопрос:

Предположим, у меня есть список номеров.

 x <- c(10,12,5,23,40,27,11,4,7,25,21,7,99,45,2,10)
 

Я хочу напечатать первые 5 чисел, превышающих 20, используя условие if внутри цикла for, поскольку это простой воспроизводимый пример, и фактический сценарий требует условий if внутри циклов. Есть ли способ получить первые 5 чисел больше 20 без ограничения диапазона? Способ найти все числа, превышающие 20, был бы примерно таким

 for(i in 1:length(x)){
if(x[i]>20){
print(x[i])
}
}
 

Проблему также можно рассматривать как ограничение инструкции print первыми 5 экземплярами.
Кто-нибудь может помочь?
Пожалуйста, обратите внимание, что диапазон цикла for не может быть ограничен для достижения решения.

Требуемым ответом было бы

 23,40,27,25,21
 

Использование для цикла, если условие и инструкция печати/cat/линии записи являются обязательными

Комментарии:

1. Нормально ли выходить из цикла , когда есть 5 попаданий, или в не упрощенном цикле происходит что-то еще, что нужно сделать для остальных.

2. Предпочтительно, чтобы вариант использования успешно прошел весь список значений и вернул первые 5, которые удовлетворяют условию. Он также должен возвращать ИСТИННЫЕ условия, даже если условие не оценивается в 5 ИСТИННЫХ условий. Например, логика должна быть для первых 5, но даже если мы получим всего 2 условия вместо максимум 5, то эти 2 должны быть напечатаны. Что касается вашего вопроса, я предполагаю, что в этом случае повторение всего цикла при выполнении первых 5 условий было бы пустой тратой памяти?

3. Спасибо. Хорошо, но тогда также было бы возможно решение, которое уже ограничивает диапазон for цикла.

4. Я тоже думал об этом. Не могли бы вы сказать мне, о чем именно вы думаете?

5. Например: for(i in which(cumsum(x > 20) <= 5)) {...

Ответ №1:

Сработает ли это:

 x[x > 20][1:5]
[1] 23 40 27 25 21
 
 

Использование для цикла:

 v <- vector()
for(i in 1:length(x)){
  if(x[i] > 20){
    v <- c(v,x[i])
  }  
  if(length(v) == 5){
    print(v)
    break
  }
}
[1] 23 40 27 25 21
 

Комментарии:

1. Это даст сомнительные результаты, если будет меньше 5 результатов.

2. В данном случае это работает. Но в случае использования требуется использовать инструкцию print внутри условия if внутри для циклов. Я постарался изложить это как можно проще!

3. @Nil_07, добавили for цикл, пожалуйста, проверьте, работает ли это

4. Я попробую это для своего случая @Karthik S. Между тем ваше решение и решение GKi ниже выглядят похожими и полезными.

5. @Nil_07, это в основном создание пустого вектора и заполнение его в соответствии с нашими условиями.

Ответ №2:

Поскольку оказалось, что ограничение диапазона цикла for разрешено, это можно было бы сделать с помощью cumsum(x > 20) <= 5 :

 for(i in seq_len(match(5, cumsum(x > 20), length(x)))) {
  if(x[i] > 20) {
    print(x[i])
  }
}
#[1] 23
#[1] 40
#[1] 27
#[1] 25
#[1] 21
 

Или добавьте счетчик:

Вариант, который сломается после 5 попаданий (благодаря @sindri-baldur):

 n <- 0L
for(i in 1:length(x)){
  if(x[i]>20) {
    print(x[i])
    n <- n 1L
    if(n == 5L) break
  }
}
 

Вариант, который сделает полный цикл.

 n <- 0L
for(i in 1:length(x)){
  if(x[i]>20 amp; n<5) {
    n <- n 1L
    print(x[i])
  }
}
 

Чтобы получить первые 5, вы можете использовать head :

 head(x[x > 20], 5)
#[1] 23 40 27 25 21
 

Обратите внимание, что это также будет работать в тех случаях, когда попаданий меньше 5. Затем он вернет количество обращений. Например, попробуйте сделать это с:

 x <- c(10,12,5,23,40,27,11,4,7,25,2,7,9,4,2,10)
 

Комментарии:

1. Я бы добавил вместо if (n == 5L) break этого в случае x , если это очень долго.

2. @sindri_baldur Я не знаю, что еще произойдет в не упрощенном цикле. И в вопросе я могу читать, не ограничивая диапазон . Но, возможно break , можно было бы использовать, но это ограничит диапазон.

3. @sindri_baldur Спасибо за подсказку. На самом деле оказывается, что ограничение диапазона допустимо. Поэтому я добавляю вариант с вашим предложением.