Member 14800672 Ответов: 2

Как обнаружить последовательные идентификаторы и сделать действие, основанное на этом?


I have a list with 2 fields Id and name
This list might have different outputs each time so for example let's say it has 5 objects
1,sun
2,mon
3,tuesday
5,thursday
6,Friday

I want to display it as
Sun-tue, thursday-friday

I mean any time the Ids are consecutive i want to put a dash, once there is a skip i want comma.. As u can see here because i skiped id of wednesday i put a comma


Что я уже пробовал:

Пожалуйста помогите я пытался но не смог этого сделать

Patrice T

Покажи свою работу.

BillWoodruff

покажите свой код

2 Ответов

Рейтинг:
12

Maciej Los

Это очень просто...

var dummydata = new[]
	{
		new{ID=1, Day="sun"},
		new{ID=2, Day="mon"},
		new{ID=3, Day="tue"},
		new{ID=5, Day="thu"},
		new{ID=6, Day="fri"}
	};

int i =0, j = 0;
string s  = string.Empty;
List<string> days = new List<string>();
while(i<dummydata.Length-1)
{
	j=i+1;
	while(j<dummydata.Length && dummydata[j].ID - dummydata[i].ID ==1) j++;
	//when single day
	if(j-i == 1)
		s = j<dummydata.Length ? dummydata[j].Day : dummydata[i].Day;
	else  //consecutive days
		s = string.Concat(dummydata[i].Day, "-", j<dummydata.Length ? dummydata[j].Day : dummydata[j-1].Day);
	days.Add(s);
	i = j+1;
}

foreach(string d in days)
{
	Console.WriteLine(d);
}
//prints:
//sun-tue
//thu-fri


Для решения linq, пожалуйста, смотрите это: Группировка результатов по смежным ключам (LINQ в C#) | Microsoft Docs[^]

или используйте этот метод расширения:
public static class Extensions
{
    public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> seq, Func<T, T, bool> condition)
    {
        T prev = seq.First();
        List<T> list = new List<T>() { prev };

        foreach (T item in seq.Skip(1))
        {
            if (condition(prev, item) == false)
            {
                yield return list;
                list = new List<T>();
            }
            list.Add(item);
            prev = item;
        }

        yield return list;
    }
}


Использование:
var consecutivedays = dummydata
    .GroupWhile((x, y) => y.ID - x.ID == 1)
    .Select(grp => string.Concat(grp.Select(x=>x.Day).First(), "-", grp.Select(x=>x.Day).Last()))
    .ToList();


Richard Deeming

Пара небольших изменений в вашем методе расширения:
* Проверка аргументов;
* Не блевать, если входная последовательность пуста;
* Только вызов GetEnumerator однажды:

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> seq, Func<T, T, bool> condition)
{
    if (seq is null) throw new ArgumentNullException(nameof(seq));
    if (condition is null) throw new ArgumentNullException(nameof(condition));
    return Iterator(seq, condition);
    
    static IEnumerable<IEnumerable<T>> Iterator(IEnumerable<T> seq, Func<T, T, bool> condition)
    {
        using (var enumerator = seq.GetEnumerator())
        {
            if (!enumerator.MoveNext()) yield break;
            
            var prev = enumerator.Current;
            var list = new List<T> { prev };
            
            while (enumerator.MoveNext())
            {
                var item = enumerator.Current;
                
                if (!condition(prev, item))
                {
                    yield return list;
                    list = new List<T>();
                }
                
                list.Add(item);
                prev = item;
            }
            
            yield return list;
        }
    }
}
:)

Maciej Los

Ричард,
вышеприведенный код - не мой... Нашли где-то несколько лет назад.

Спасибо вам за ваш ценный комментарий.

Я бы предложил опубликовать ваш комментарий в качестве решения.

Овации,
Мацей!

Member 14800672

используя первый код, он не работает

var data = new[]
{
new{ID=1, Day="солнце"},
new{ID=3, Day="Вт"},
new{ID=5, Day="thu"},
new{ID=7, Day="Sat"}
};
если данные такие,то я получаю только Вт и СБ..в то время как я должен получить ВС,Вт,Чт, Сб ( я хочу, чтобы они были разделены комментарием, а не новой строкой)

кроме того, если данные есть
var data = new[]
{
new{ID=1, Day="солнце"},
new{ID=2, Day="mon"},
new{ID=3, Day="Вт"},
new{ID=7, Day="Sat"}
};

я должен получить ВС-вт,сб

Maciej Los

Итак, улучшите его в соответствии с вашими потребностями.

Рейтинг:
1

OriginalGriff

Да ладно тебе - ты можешь что-нибудь сделать сама?
Вы даже не показали нам никаких признаков попытки сделать это - и это тривиальная задача!

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

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

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

Точно такой же процесс, как вы бы использовали, чтобы сделать это вручную, на самом деле ...

Так что попробуйте: мы здесь не для того, чтобы делать все за вас!