如何获取仅具有相同名称的相邻项目的列表

时间:2020-07-04 03:26:28

标签: c# linq

我有一个看起来像这样的列表:

public static void main {
   int itemToBeSearched = 4;

   List<Item> list = new List<Item>();
        list.Add(new Item { Id = 1, Name = "name1" });
        list.Add(new Item { Id = 2, Name = "name2" });
        list.Add(new Item { Id = 3, Name = "name1" });
        list.Add(new Item { Id = 4, Name = "name1" });
        list.Add(new Item { Id = 5, Name = "name1" });
        list.Add(new Item { Id = 6, Name = "name3" });
        list.Add(new Item { Id = 7, Name = "name1" });

    //I need help in getting a return here
    var subList = GetAdjacentList(list, itemToBeSearched);
}

public List<Item> GetAdjacentList(List list, int itemToBeSearched)
{
    //Need help with the logic or linq here that would give a return such as
    return List<Item> list = new List<Item>();
        list.Add(new Item { Id = 3, Name = "name1" });
        list.Add(new Item { Id = 4, Name = "name1" });
        list.Add(new Item { Id = 5, Name = "name1" });
}

所需的输出应该是:仅包含Item2, Item3Item4的子列表。

我只希望返回仅包含Item3, Item4Item5的子列表,因为它们与 相邻 > 相同的名称,即name1

尽管

Item1Item7的名称不为name1,但由于它们不靠近相邻的组,因此不包括在内。

有人可以用Linq或其他方式帮助我解决此问题吗?

3 个答案:

答案 0 :(得分:2)

可能有一种更简单的方法,但我想出了这一点。它不使用任何LINQ,但可以维护列表项的顺序(假设这很重要)。

public static List<Item> GetAdjacentList(List<Item> list, int itemToBeSearched)
{
    List<Item> result = new List<Item>();
    // find the index of the item we're searching for
    int itemIdx = list.FindIndex(i => i.Id == itemToBeSearched);
    if (itemIdx == -1)
    {
        return result; // not found, return empty list
    }

    // store the item for comparisons
    Item item = list[itemIdx];

    // loop backwards starting from the current item ann going to the 0th element
    for (int i = itemIdx; i >= 0; --i)
    {
        // if this item is the search item, or the name matches, add it to the list
        if (i == itemIdx || list[i].Name == item.Name)
        {
            result.Add(list[i]);
        }
        else
        {
            // exit the loop as we've run out of items with the same name
            break;
        }
    }

    if (result.Count > 0)
    {
        result.Reverse(); // we've added items in reverse order, so reverse the list
    }

    // loop through all the items from the next item to the end of the list
    for (int i = itemIdx + 1; i < list.Count; ++i)
    {
        // if the name matches add it to the result list
        if (list[i].Name == item.Name)
        {
            result.Add(list[i]);
        }
        else
        {
            // we've reached the end of matching names so break
            break;
        }
    }
    // return the result
    return result;
}

答案 1 :(得分:1)

您没有提到当有两组连续的ID时会发生什么。例如,

enter image description here

案例1 :检索为两个单独的组

假设您想将两个组的岛作为单独的集合进行检索,则可以按以下方式修改方法。

public IEnumerable<IEnumerable<Item>> GetAdjacentList(List<Item> list, int itemToBeSearched)
{
    var nameToBeSearched = list.First(x=>x.Id==itemToBeSearched).Name;
    return list.Where(x=>x.Name.Equals(nameToBeSearched))
                .GroupWhile((x, y) => y.Id - x.Id == 1)
                .Where(x=>x.Count()>1);
}

GroupWhile被定义为

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;
    }
}

输出

enter image description here

案例2 :作为单个合并组检索

如果要将两个岛组合并为一个,则可以将上述方法修改为

public IEnumerable<Item> GetAdjacentList(List<Item> list, int itemToBeSearched)
{
    var nameToBeSearched = list.First(x=>x.Id==itemToBeSearched).Name;
    return list.Where(x=>x.Name.Equals(nameToBeSearched))
                .GroupWhile((x, y) => y.Id - x.Id == 1)
                .Where(x=>x.Count()>1).SelectMany(x=>x);
}

输出

enter image description here

答案 2 :(得分:0)

您可以使用简单的向后和向前循环在给定范围内查找具有特定名称的相邻项目,并返回与项目相同顺序的List<Item>

public List<Item> GetAdjacentList(List<Item> list, int itemToBeSearched, int range)
{
    var result = new List<Item>();
    var tar = list.FirstOrDefault(x => x.Id == itemToBeSearched);

    if (tar == null) return result;

    var indx = list.IndexOf(tar);
            
    for (var i = indx - 1; i >= (indx - range); i--)
    {
        if (i >= 0 && list[i].Name.Equals(tar.Name, 
            StringComparison.CurrentCultureIgnoreCase))
            result.Insert(0, list[i]);
        else
            break;
    }

    result.Add(list[indx]);

    for (var i = indx + 1; i <= (indx + range) ; i++)
    {
        if (i < list.Count() && list[i].Name.Equals(tar.Name, 
            StringComparison.CurrentCultureIgnoreCase))
            result.Add(list[i]);
        else
            break;
    }
    return result;
}

给定的List<Item>示例(rang = 1)的输出:

The adjacent items of ID 1 => 1       (name1)
The adjacent items of ID 2 => 2       (name2)
The adjacent items of ID 3 => 3, 4    (name1)
The adjacent items of ID 4 => 3, 4, 5 (name1)
The adjacent items of ID 5 => 4, 5    (name1)
The adjacent items of ID 6 => 6       (name3)
The adjacent items of ID 7 => 7       (name1)