Как получить данные, которые идут подряд
Есть List<DB>
class DB
{
int id { get; set; }
decimal win { get; set; }
decimal credit { get; set; }
}
id win credit
1 10 100
2 12 105
3 9 109
4 11 109
5 5 109
6 4 109
7 3 95
8 2 115
Как узнать с какого по какой индекс идут строки, с одинаковым credit. Допустим будет переменная n-количество совпадений идущие больше 4 раз подряд(>=). Вот как найти эти индексы?
В моем примере выше это с 3 по 6 строки
Ответы (1 шт):
Как один из вариантов, который написан на коленке:
int startIdex = -1;
var result = new List<(decimal Credit, Range Range)>();
for (int i = 0; i < data.Count; i++)
{
var current = data[i];
var next = i + 1 < data.Count ? data[i+1] : null;
if (current.Credit == next?.Credit)
{
if (startIdex == -1)
startIdex = i;
}
else
{
if (startIdex == -1)
{
result.Add((current.Credit, new Range(i, i+1)));
}
else
{
result.Add((current.Credit, new Range(startIdex, i+1)));
startIdex = -1;
}
}
}
Поясняю что тут да как:
new List<(decimal Credit, Range Range)>- тут все зависит от того, как вид вы хотите. Можно сделать класс, содержащий в себе эти данные, можно сделатьDictionary, у которого ключом будетRange, мне лично так было удобней)for (int i = 0; i < data.Count; i++)- простой цикл, который даст текущий индекс (что нам и нужно).var current = data[i];- текущий объект.var next = i + 1 < data.Count ? data[i+1] : null;- следующий объект в коллекции. Если индекс за пределами, то возвращаемNULL.if (current.Credit == next?.Credit)- Если текущее значение и следующее равны, то...if (startIdex == -1)- дабы нам не менять каждую иттерацию стартовый индекс, есть эта проверка, которая меняет его значение лишь в тот момент, когда первый раз было найдено повторяющееся значение.- блок
else- тут думаю все понятно, если у нас текущее значение не повторяется со следующим, то мы проверяем изменениеstartIndex, если оно со стандартным значением-1, то просто добавляем новый объект, гдеRangeбудет отiдоi+1, если же стартовый индекс был изменен, то добавляем уже нужный намRangeотstartIndexдоi+1, ну и сбрасываем этот индекс.
То есть, наша логика такая:
- Проверяем текущее и следующее значение
- Если они равны, то записываем стартовый индекс.
- Если они не равны, то:
- Если индекс был изменен - добавляем в результат значение с
Range(стартовыйИндекс, текущий+1). - Если индекс не изменен - добавляем в результат значение с
Range(текущий, текущий+1).
- Если индекс был изменен - добавляем в результат значение с
В итоге мы получим примерно следующее:
(100, 0..1)
(105, 1..2)
(109, 2..6)
(95, 6..7)
(115, 7..8)
Сами данные:
0. 100
1. 105
2. 109
3. 109
4. 109
5. 109
6. 95
7. 115
И видим, что 109-е значение идет с 2 и до 6 индека (помним, что подсчет индексов в C# идет с 0!).
Тут можно провести еще различные улучшения, но саму суть думаю вы теперь поняли. Также выводимый результат смотрите сами какой вам нужен, к примеру, можете брать не индекс (i), а id из класса db, думаю труда вам это не составит.
А дальше уже поступайте с этими данными так, как вашей душе будет угодно, например:
var range = ranges.FirstOrDefault(x => x.Credit == 109);
var items = data[range.Range];
P.S. Range были добавлены в C#8. Если по каким-то причинам вам это не подходит, то уж извиняйте, придется писать свои костыли.
Пример онлайн