я могу сделать что-то вроде цикла foreachtime (вот как я буду ссылаться на него) в C #? - PullRequest
0 голосов
/ 16 сентября 2018

Я кое-что изучил и не могу найти хороший способ сделать это.У меня есть функциональный код, но я хочу очистить его, не используя ручной подсчет или разрывы.Я посмотрел на функцию LINQs TakeWhile, но в данном случае этого недостаточно.Вот пример работающей реализации функционального эквивалента:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    for(int i=0; i<stringList.Count && !found; i++)
    {
        if(stringlist[i].length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

И я хочу заменить его на некоторую «волшебную» функцию, подобную этой:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    foreachwhile(string s in stringList while !found)
    {
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

Есть ли какая-то функциякоторый может сделать это уже, и если нет, как я могу написать один на C # ... или приблизиться?Я часто нахожу, что мне нужно это сделать, и да, я знаю, что:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    foreach(string s in stringList)
    {
        if(found)
            break;
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

технически тоже работает, но я бы хотел избежать разрывов в моем коде.Есть ли другой чистый способ сделать это в c #?

РЕДАКТИРОВАТЬ: Я вижу много путаницы в отношении того, что я здесь спрашиваю.Я бы предпочел способ добавить очень четкую проверку, если мы должны прервать работу самого оператора foreach, если это возможно, или способ написать мою собственную версию foreach, которая принимает параметр, который продолжается только тогда, когда условие истинно, напримерпуть еще не найден.

Кроме того, я прошу прощения за непонятность, но самая большая причина, по которой я хочу избежать разрыва, состоит в том, что я не выпрыгиваю из цикла в произвольной точке.В этом отношении возврат так же нежелателен.

Я тоже ничего не имею против Linq, я пытался его использовать, но я обнаружил, что он не обеспечивает нужную мне функциональность:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    bool found= false;
    foreach(string s in stringlist.Takewhile(x=> (!found)))
    {
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }
    return found
}

отличается от описанной выше логики, посколькуTakeWhile выполняется первым и возвращает пустой набор, в результате чего в цикле foreach больше нечего зацикливаться.Если у кого-то есть другой способ написать это, я искренне хотел бы услышать это, поскольку синтаксически это выглядит чрезвычайно чистым.

Ответы [ 3 ]

0 голосов
/ 16 сентября 2018

Не уверен, что делает ваш код;но с помощью Linq Any получается то же самое.

bool foo(List<string> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
            {
                return stringList.Any(s =>
                {
                    var found = s.Length < 2 || counter >= 6;
                    counter++;
                    return found;
                });            
            }
0 голосов
/ 16 сентября 2018

Если вы настаиваете на том, чтобы не использовать брейк, альтернативный способ - использовать делегатов, хотя использование брейка - это лучшая практика.

...

bool found= false;
Action Search = () =>
{
    foreach(string s in stringList)
    {
        if(s.length < 2 || counter >=6)
            found=true;
            return;
        counter++;
    }
}

Search();

...

Не используйте этот код. Используйте перерыв.

0 голосов
/ 16 сентября 2018

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

Например, ваш метод может вернуть логическую комбинацию нескольких различных частей логики, каждый из которых делегирован своему методу.Показанный фрагмент логики может быть делегирован другому методу следующим образом.

Я бы использовал break, поскольку он предназначен для выполнения именно того, что вы хотите, и в этом нет ничего плохого.Но для вашего конкретного примера вы также можете избежать прерывания, как это ...

bool foo_part2(List<strings> stringList, int counter)
{
    foreach (string s in stringList)
    {
        if(s.length < 2 || counter >=6)
            return true;
        counter++;
    }
    return false;
}

... И оригинальный метод будет выглядеть примерно так ...

bool foo(List<strings> stringList, int counter)
{
    return foo_part1(stringList,counter) ||
        foo_part2(stringList,counter) ||
        foo_part3(stringList,counter);
}

(Выможет потребоваться использовать && s вместо ||, в зависимости от требуемой логики.) При правильно названных методах (а не в этом примере "foo") это может быть очень легко читаемо, и вам не придется искатьв функцию, чтобы увидеть, что он делает.

Однако, чтобы заключить ... в этом вопросе есть ошибка.Вы утверждаете «Я тоже ничего не имею против Linq, я пытался его использовать, но я обнаружил, что он не обеспечивает нужную мне функциональность ... потому что TakeWhile выполняется первым» .Это не правильно.Это означает, что вы не сами попробовали, и что вы не поняли ответ, который вы получили на свой предыдущий вопрос за 20 минут до того, как задать этот .Он использует предикат, поэтому значение оценивается каждый раз через итерацию, что является точно тем, что вы хотите.Таким образом, весь этот вопрос ошибочен, и если бы вы только что попробовали его сами (даже прежде, чем задать свой предыдущий вопрос), вы бы сами решили это.

Я отсылаю ОП квопрос Сколько исследовательских работ ожидается от пользователей Stack Overflow? .

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