如何使用linq从列表中删除尾随对象?

时间:2016-11-28 18:22:47

标签: c# linq

我有一组带有属性的对象,我希望在LINQ中删除(例如)值为0的所有尾随对象。

public class Object
{
    public Object(){}

    public int Property {get; set;}
}

如果我有一个对象列表:

new Object(){ Property = 1};
new Object(){ Property = 0};
new Object(){ Property = 9};
new Object(){ Property = 7};
new Object(){ Property = 0}; // "trailing zero"
new Object(){ Property = 0}; // "trailing zero"
new Object(){ Property = 0}; // "trailing zero"

如何删除此列表中的“尾随零”?我不想删除所有属性为零的属性,但我想从列表中删除属性值为零的任何对象,如果它后面没有更大的属性值。

4 个答案:

答案 0 :(得分:6)

有限大小序列的标准解决方案 - 反向,从开始移除,反向:

   var withoutTail = sequence
       .Reverse()
       .SkipWhile( x => x == 0) // whatever condition you need
       .Reverse();

这非常不理想,所以如果你真的有真正的集合(即List),那么从最后一个索引开始删除项目会更好。

答案 1 :(得分:4)

编写扩展方法:

static class Extensions
{
    public static IEnumerable<T> TrimTrailing<T>(this IEnumerable<T> items,
                                                 Predicate<T> test)
    {

        if (items == null) throw new ArgumentNullException(nameof(items));
        if (test == null) throw new ArgumentNullException(nameof(test));

        var buf = new List<T>();
        foreach (T item in items)
        {
            if (test(item))
            {
                buf.Add(item);
            }
            else
            {
                foreach (T bufferedItem in buf)
                {
                    yield return bufferedItem;
                }
                buf.Clear();
                yield return item;
            }
        }
    }
}

然后,如果您有一个名为IEnumerable<Object>的{​​{1}},则可以使用

拨打l
TrimTrailing

小心这一点,但是:在最坏的情况下,它会缓冲var trimmed = l.TrimTrailing(o => o.Property == 0); 中的所有项目,然后抛弃缓冲区。

答案 2 :(得分:3)

向后迭代您的列表,删除所有Property != 0条目,并停在列表的开头或for (int i = list.Count - 1; i >= 0; i--) { var item = list[i]; if (item.Property == 0) { list.RemoveAt(i); } else { break; } }

{{1}}

这将允许您通过列表进行单次传递。

答案 3 :(得分:1)

您可以使用FindLastIndex查找最后一个非0索引,以及Take之前的元素。

var result = list.Take(list.FindLastIndex(x => x.Property != 0) + 1);