Подсчёт элементов с последующим проходом по последовательнос
От: _NN_ www.nemerleweb.com
Дата: 15.01.23 13:59
Оценка:
Имеем обобщённую (IEnumerable<T>) последовательность, например:

1, 1, 1, 2, 3, 3, 3


Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз, после этого ничего быть не должно.

Это не валидно:
1, 1, 3
1, 2, 2, 3
1, 2, 3, 4


На данный момент самый простой рукопашный код будет примерно таким, для простоты выбран IEnumerable<int>.
Хотелось бы это реализовать встроенными средствами LINQ, но засада в том, что TakeWhile не даёт продолжение последовательности, а SkipWhile не даёт информацию сколько было пропущено, а CountWhile вообще такого нет.
Подскажите идеи

        static void Test(IEnumerable<int> seq)
        {
            using var enumerator = seq.GetEnumerator();

            // 1+
            bool hasNext1 = false;
            bool has1 = false;
            while (enumerator.MoveNext())
            {
                if (enumerator.Current != 1) // predicate1
                {
                    hasNext1 = true;
                    break;
                }
                has1 = true;
            }

            if (!has1)
            {
                Console.WriteLine("No 1");
                return;
            }

            if (!hasNext1)
            {
                Console.WriteLine("No elements");
                return;
            }

            // 2
            bool hasNext2 = false;
            bool has2 = false;
            do
            {
                if (enumerator.Current != 2) // predicate2
                {
                    hasNext2 = true;
                    break;
                }
                if (has2)
                {
                    Console.WriteLine("2 is more than once !");
                    return;
                }

                has2 = true;
            } while (enumerator.MoveNext());

            if (!has2)
            {
                Console.WriteLine("No 2");
                return;
            }

            if (!hasNext2)
            {
                Console.WriteLine("No elements");
                return;
            }

            // 3+
            bool hasNext3 = false;
            bool has3 = false;
            do
            {
                if (enumerator.Current != 3) // predicate3
                {
                    hasNext3 = true;
                    break;
                }
                has3 = true;
            } while (enumerator.MoveNext());

            if (!has3)
            {
                Console.WriteLine("No 3");
                return;
            }

            if (hasNext3)
            {
                Console.WriteLine("Too many elements");
                return;
            }

            Console.WriteLine("OK");
        }
http://rsdn.nemerleweb.com
http://nemerleweb.com
Отредактировано 15.01.2023 15:01 _NN_ . Предыдущая версия .
Re: Подсчёт элементов с последующим проходом по последовательности
От: Baiker  
Дата: 15.01.23 14:58
Оценка: -1
Здравствуйте, _NN_, Вы писали:

_NN>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз


ээ... а регэкспы разве не решат такую задачу?
Re[2]: Подсчёт элементов с последующим проходом по последовательности
От: _NN_ www.nemerleweb.com
Дата: 15.01.23 15:00
Оценка:
Здравствуйте, Baiker, Вы писали:

B>Здравствуйте, _NN_, Вы писали:


_NN>>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз


B>ээ... а регэкспы разве не решат такую задачу?

Помогли бы если бы это была строка, но тут не строка.
Как раз построение автомата из реализации регэкспов могло бы помочь, но это внутренняя реализация.

У меня общий IEnumerable<T> и общие предикаты Func<T, bool>, числа даны для простоты.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Подсчёт элементов с последующим проходом по последовател
От: rameel https://github.com/rsdn/CodeJam
Дата: 15.01.23 16:01
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Хотелось бы это реализовать встроенными средствами LINQ, но засада в том, что TakeWhile не даёт продолжение последовательности, а SkipWhile не даёт информацию сколько было пропущено, а CountWhile вообще такого нет.


А GroupWhile не подойдет? https://github.com/rsdn/CodeJam/blob/master/CodeJam.Main/Collections/Enumerable/EnumerableExtensions.GroupWhile.cs
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Отредактировано 15.01.2023 16:02 rameel . Предыдущая версия .
Re[2]: Подсчёт элементов с последующим проходом по последовател
От: _NN_ www.nemerleweb.com
Дата: 15.01.23 16:09
Оценка:
Здравствуйте, rameel, Вы писали:

R>Здравствуйте, _NN_, Вы писали:


_NN>>Хотелось бы это реализовать встроенными средствами LINQ, но засада в том, что TakeWhile не даёт продолжение последовательности, а SkipWhile не даёт информацию сколько было пропущено, а CountWhile вообще такого нет.


R>А GroupWhile не подойдет? https://github.com/rsdn/CodeJam/blob/master/CodeJam.Main/Collections/Enumerable/EnumerableExtensions.GroupWhile.cs


Не совсем.
Тут дело в том, что часть последовательности мы обрабатываем энергично, а остальную часть лениво.
Методы расширения обычно обходят всю последовательность либо только энергично либо только лениво.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Подсчёт элементов с последующим проходом по последовательнос
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.23 16:27
Оценка: 12 (1)
Здравствуйте, _NN_, Вы писали:

_NN>Имеем обобщённую (IEnumerable<T>) последовательность, например:


_NN>
_NN>1, 1, 1, 2, 3, 3, 3
_NN>


_NN>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз, после этого ничего быть не должно.


using System;
using System.Linq;

var xs = new[] {1, 1, 1, 2, 3, 3, 3};

var x = xs.Aggregate(1, (s, x) => (s, x) switch {
    (1,1) => 1,
    (1,2) => 2,
    (2,3) => 3,
    (3,3) => 3,
    _ => -1
});
Console.WriteLine(x);
Re[2]: Подсчёт элементов с последующим проходом по последовательнос
От: _NN_ www.nemerleweb.com
Дата: 15.01.23 16:59
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, _NN_, Вы писали:


_NN>>Имеем обобщённую (IEnumerable<T>) последовательность, например:


_NN>>
_NN>>1, 1, 1, 2, 3, 3, 3
_NN>>


_NN>>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз, после этого ничего быть не должно.


G>
G>using System;
G>using System.Linq;

G>var xs = new[] {1, 1, 1, 2, 3, 3, 3};

G>var x = xs.Aggregate(1, (s, x) => (s, x) switch {
G>    (1,1) => 1,
G>    (1,2) => 2,
G>    (2,3) => 3,
G>    (3,3) => 3,
G>    _ => -1
G>});
G>Console.WriteLine(x);

G>



Это подходит если не нужны дополнительные действия над элементами.
А вот если нужна обработка для условия как у меня, то не подойдёт.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Подсчёт элементов с последующим проходом по последовательнос
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.23 17:12
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Это подходит если не нужны дополнительные действия над элементами.

Используйте Aggregate c resultSelector

_NN>А вот если нужна обработка для условия как у меня, то не подойдёт.

Какая у вас обработка? Я не вижу.
Re[4]: Подсчёт элементов с последующим проходом по последовательнос
От: _NN_ www.nemerleweb.com
Дата: 15.01.23 17:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Здравствуйте, _NN_, Вы писали:


_NN>>Это подходит если не нужны дополнительные действия над элементами.

G>Используйте Aggregate c resultSelector

_NN>>А вот если нужна обработка для условия как у меня, то не подойдёт.

G>Какая у вас обработка? Я не вижу.

Код более менее такой:
record A(int X);

bool Is1(A a) => a.X == 1;
bool Is2(A a) => a.X == 2;
bool Is3(A a) => a.X == 3;

var xs = new A[] { new(1), new(1), new(1), new(2), new(3), new(3), new(3) };

// Нужна последовательность A.X в вышеуказанном порядке "1" несколько раз, "2" один раз, "3" несколько раз, конец.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Подсчёт элементов с последующим проходом по последовательнос
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.01.23 18:04
Оценка: 169 (5)
Здравствуйте, _NN_, Вы писали:

_NN>Код более менее такой:

_NN>
_NN>record A(int X);

_NN>bool Is1(A a) => a.X == 1;
_NN>bool Is2(A a) => a.X == 2;
_NN>bool Is3(A a) => a.X == 3;

_NN>var xs = new A[] { new(1), new(1), new(1), new(2), new(3), new(3), new(3) };

_NN>// Нужна последовательность A.X в вышеуказанном порядке "1" несколько раз, "2" один раз, "3" несколько раз, конец.
_NN>


using System;
using System.Linq;

var xs = new A[] {new(1), new(1), new(1), new(2), new(3), new(3), new(3)};

var x = xs.Aggregate(1, (s, a) => (s, a) switch {
    (1,var m) when Is1(m) => 1,
    (1,var m) when Is2(m) => 2,
    (2,var m) when Is3(m) => 3,
    (3,var m) when Is3(m) => 3,
    _ => -1
});
Console.WriteLine(x);

bool Is1(A a) => a.x == 1;
bool Is2(A a) => a.x == 2;
bool Is3(A a) => a.x == 3;

record A(int x);
Re[6]: Подсчёт элементов с последующим проходом по последовательнос
От: _NN_ www.nemerleweb.com
Дата: 16.01.23 09:56
Оценка:
Здравствуйте, gandjustas, Вы писали:

Спасибо.
Интересная идея.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Подсчёт элементов с последующим проходом по последовательнос
От: Sharov Россия  
Дата: 16.01.23 10:22
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Имеем обобщённую (IEnumerable<T>) последовательность, например:


_NN>
_NN>1, 1, 1, 2, 3, 3, 3
_NN>


_NN>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз, после этого ничего быть не должно.


Пройтись циклом и перегнать в словарь, по ходу проверяя кол-во эл-ов. Типа если 2 уже есть, то ошибка.
Кодом людям нужно помогать!
Re[2]: Подсчёт элементов с последующим проходом по последовательнос
От: _NN_ www.nemerleweb.com
Дата: 16.01.23 10:23
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, _NN_, Вы писали:


_NN>>Имеем обобщённую (IEnumerable<T>) последовательность, например:


_NN>>
_NN>>1, 1, 1, 2, 3, 3, 3
_NN>>


_NN>>Требуется убедиться, что есть 1 как минимум один раз, 2 только один раз, и 3 как минимум один раз, после этого ничего быть не должно.


S>Пройтись циклом и перегнать в словарь, по ходу проверяя кол-во эл-ов. Типа если 2 уже есть, то ошибка.


Тогда нет проверки порядка и лишних элементов.
Тут в ветке подсказали достаточно лаконичное решение.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Подсчёт элементов с последующим проходом по последовательнос
От: Sharov Россия  
Дата: 16.01.23 11:06
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Тогда нет проверки порядка и лишних элементов.


Проверка порядка -- отдельная переменная, лишние эл-ты -- hashset (hs.Contains())

_NN>Тут в ветке подсказали достаточно лаконичное решение.


Не спорю, изящное решение.
Кодом людям нужно помогать!
Re: Подсчёт элементов с последующим проходом по последовательнос
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.01.23 11:29
Оценка: 30 (3) +1
Здравствуйте, _NN_, Вы писали:

Вот тут не очень лаконичное, но более общее:
    public static void Main()
    {
        var e = EnEx.MatchOneOrMore(1).ThenOne(2).ThenOneOrMore(3).ThenEnd();
        
        var tests = new[]{ 
            new [] {1, 1, 1, 2, 3, 3, 3},
            new [] {1, 1, 3},
            new [] {1, 2, 2, 3},
            new [] {1, 2, 3, 4}
        };
        
        foreach(var test in tests)
        {
            Console.WriteLine($"{string.Join(' ', test)}: {e.IsMatch(test)}");
        }
        
    }
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.