Раздел с использованием Linq - PullRequest
0 голосов
/ 19 сентября 2018

Вот моя проблема, у меня есть набор результатов запроса, который выглядит следующим образом:

id_1  - 0 - datetime - gps coordinates  
id_2  - 0 - datetime - gps coordinates
id_3  - 1 - datetime - gps coordinates 
id_4  - 1 - datetime - gps coordinates 
id_5  - 1 - datetime - gps coordinates
id_6  - 1 - datetime - gps coordinates 
id_7  - 0 - datetime - gps coordinates 
id_8  - 0 - datetime - gps coordinates 
id_9  - 0 - datetime - gps coordinates 
id_10 - 0 - datetime - gps coordinates
id_11 - 1 - datetime - gps coordinates 
id_12 - 1 - datetime - gps coordinates 
id_13 - 0 - datetime - gps coordinates 
id_14 - 0 - datetime - gps coordinates

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

List1: [id_3], [...] , [id_6]
List2: [id_11], [...], [id_12]

Я не знаю количество элементов с 0 или 1, так что это имеетчтобы быть обобщенным в этом смысле

Я использую C # 4.5, и думал об использовании Linq для этого вместо старомодного foreach.

Может ли кто-нибудь указать мне правильное направление

Ответы [ 3 ]

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

Если вы хотите избежать foreach, вот способ сделать это с расширением LINQ Aggregate.

Учитывая следующий класс:

public class SomeType 
{
    public int Id {get;set;}
    public int Val {get;set;}
}

и сгенерировав следующие элементы:

var items = new List<SomeType>();
for(var i = 1; i <= 14; i++) 
{
    var val = 0;
    if((3 <= i && i <= 6) || (11 <= i && i <= 12))
        val = 1;
    items.Add(new SomeType { Id = i, Val = val});
}

Вы можете получить список списков элементов со значением 1, например, так:

var grouped = items.Aggregate(new List<List<SomeType>>() { new List<SomeType>() },
    (acc,elem) => 
    { 
        if(elem.Val == 0 && acc.Last().Count != 0)  
            acc.Add(new List<SomeType>());
        else if(elem.Val == 1)
            acc.Last().Add(elem);
        return acc;
    }, acc => acc.Where(x => x.Count != 0));

int groupNum = 1;
foreach (var group in grouped)
{
    Console.WriteLine($"Group {groupNum++}");
    foreach (var item in group)
        Console.WriteLine($"{item.Id} - {item.Val}");
}

/* output:
Group 1
3 - 1
4 - 1
5 - 1
6 - 1
Group 2
11 - 1
12 - 1
*/

Это предполагает, что можно добавлять записи со значением 1 перед 0значение произошло, и я не уверен, что это особенно удобочитаемо, чем использование foreach, и вам, вероятно, лучше реализовать метод расширения, который в любом случае будет использовать foreach.

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

Попробуйте это решение ;

var prev = 0;
List<int> bag = null;
var result = new List<List<int>>();

foreach(var item in list)
{
    if(item.Val == 1)
    {
        if(prev == 0)
        {
            if(bag != null)
                result.Add(bag);
            bag = new List<int>();
        }                       
        bag.Add(item.Id);
    }
    prev = item.Val;
}
if(bag != null)
    result.Add(bag);

result.ForEach(x => {           
    Console.WriteLine(String.Join(", ", x));
});
//3, 4, 5, 6
//11, 12
0 голосов
/ 19 сентября 2018

Я не думаю, что в фреймворке есть что-то встроенное, но вы можете создать для него метод расширения:

public static class LinqHelper
{
    public static IEnumerable<List<Item>> Partition(this IEnumerable<Item> source, Func<Item, bool> selector)
    {
        List<Item> currentList = new List<Item>();

        foreach (var item in source)
        {
            if (selector(item))
            {
                currentList.Add(item);
            }
            else if (currentList.Count != 0)
            {
                yield return currentList;
                currentList = new List<Item>();
            }
        }

        if (currentList.Count != 0)
        {
            yield return currentList;
        }
    }
}

public class Item
{
    public int Id { get; set; }
    public int Val { get; set; }
}

void Main()
{
    var list = new List<Item>(){
        new Item{ Id = 1, Val = 0 },
        new Item{ Id = 2, Val = 0 },
        new Item{ Id = 3, Val = 1 },
        new Item{ Id = 4, Val = 1 },
        new Item{ Id = 5, Val = 1 },
        new Item{ Id = 6, Val = 1 },
        new Item{ Id = 7, Val = 0 },
        new Item{ Id = 8, Val = 0 },
        new Item{ Id = 9, Val = 0 },
        new Item{ Id = 10, Val = 0 },
        new Item{ Id = 11, Val = 1 },
        new Item{ Id = 12, Val = 1 },
        new Item{ Id = 13, Val = 0 },
        new Item{ Id = 14, Val = 0 },
    };

    var result = list.Partition(i => i.Val == 1).Where(i => true).ToList();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...