修剪列表的最佳方法是什么

本文关键字:方法 是什么 最佳 列表 修剪 | 更新日期: 2023-09-27 18:21:45

我有一个字符串列表。它在其他地方生成,但我将在下面生成它,以帮助描述这个简化的示例

var list = new List<string>();
list.Add("Joe");
list.Add("");
list.Add("Bill");
list.Add("Bill");
list.Add("");
list.Add("Scott");
list.Add("Joe");
list.Add("");
list.Add("");
list = TrimList(list);

我想要一个函数"trims"这个列表,通过修剪,我想删除数组末尾的所有空字符串项(在这种情况下是最后两个)。

注意:我仍然想保留数组中第二个项的空白项(或不在末尾的任何其他项),这样我就不能执行.Where(r=> String.isNullOrEmpty(r))

修剪列表的最佳方法是什么

老实说,我只会在没有任何LINQ的情况下编写它——毕竟,你正在修改一个集合,而不仅仅是查询它:

void TrimList(List<string> list)
{
    int lastNonEmpty = list.FindLastIndex(x => !string.IsNullOrEmpty(x));
    int firstToRemove = lastNonEmpty + 1;
    list.RemoveRange(firstToRemove, list.Count - firstToRemove);
}

如果你真的想创建一个新的列表,那么基于LINQ的解决方案是可以的。。。尽管可能有些低效(因为Reverse必须缓冲所有内容)。

利用ReverseSkipWhile

list = list.Reverse().SkipWhile(s => String.IsNullOrEmpty(s)).Reverse().ToList();

List<T>(不是接口)有一个FindLastIndex方法。因此,你可以用一种方法来包装它:

static IList<string> TrimList(List<string> input) {
    return input.Take(input.FindLastIndex(x => !string.IsNullOrEmpty(x)) + 1)
        .ToList();
}

这会生成一个副本,而Jon会修改列表。

我能想到的唯一解决方案是编写一个循环,从列表的末尾开始,搜索一个不是空字符串的元素。不知道有什么库函数会有帮助。一旦你知道了最后一个好元素,你就知道该删除哪些了。

在迭代集合时要小心不要修改它。这会破坏迭代器。

我总是喜欢想出最通用的解决方案。为什么要用列表和字符串来限制自己?让我们为泛型枚举生成一个算法!

public static class EnumerableExtensions
{
    public static IEnumerable<T> TrimEnd<T>(this IEnumerable<T> enumerable, Predicate<T> predicate)
    {
        if (predicate == null)
        {
            throw new ArgumentNullException("predicate");
        }
        var accumulator = new LinkedList<T>();
        foreach (var item in enumerable)
        {
            if (predicate(item))
            {
                accumulator.AddLast(item);
            }
            else
            {
                foreach (var accumulated in accumulator)
                {
                    yield return accumulated;
                }
                accumulator.Clear();
                yield return item;
            }
        }
    }
}

这样使用:

var list = new[]
{
    "Joe", 
    "", 
    "Bill", 
    "Bill", 
    "", 
    "Scott", 
    "Joe", 
    "", 
    ""
};
foreach (var item in list.TrimEnd(string.IsNullOrEmpty))
{
    Console.WriteLine(item);
}