删除List <string>?</string>的开头和结尾处的空行

时间:2013-03-12 09:50:21

标签: c# .net string

鉴于List<string>我需要删除列表开头和结尾的所有空行

注意:我认为空行是没有内容的行,但可能包含空格和制表符。这是检查行是否为空的方法:

    private bool HasContent(string line)
    {
        if (string.IsNullOrEmpty(line))
            return false;

        foreach (char c in line)
        {
            if (c != ' ' && c != '\t')
                return true;
        }

        return false;
    }

您建议使用哪些有效且可读的代码?

确认示例

[" ", " ", " ", " ", "A", "B", " ", "C", " ", "D", " ", " ", " "]

应该修剪这样的列表,方法是删除开头的所有空行结束以下结果:

["A", "B", " ", "C", " ", "D"]

10 个答案:

答案 0 :(得分:8)

var results = textLines1.SkipWhile(e => !HasContent(e))
                        .Reverse()
                        .SkipWhile(e => !HasContent(e))
                        .Reverse()
                        .ToList();

它是如何工作的?从列表中跳过所有空行,反转它并执行相同操作(实际上跳过列表后面的所有空行)。经过另一次逆转后,你会得到正确的结果。

如果列表非常庞大,您可以考虑使用标准while循环并列出索引,因为性能方面的考虑因素,但对于正常数据,传递回归应该不重要。

答案 1 :(得分:4)

首先,有一个内置方法可以检查:String.IsNullOrWhitespace();

ColinE提供的答案不符合要求,因为它删除了所有空行,而不仅仅是在开头或结尾。

我认为你需要建立自己的解决方案:

int start = 0, end = sourceList.Count - 1;

while (start < end && String.IsNullOrWhitespace(sourceList[start])) start++;
while (end >= start && String.IsNullOrWhitespace(sourceList[end])) end--;

return sourceList.Skip(start).Take(end - start + 1);

答案 2 :(得分:2)

使用Linq,您可以执行以下操作:

IEnumerable<string> list  = sourceList.SkipWhile(source => !HasContent(source))
                                      .TakeWhile(source => HasContent(source));

这&#39;跳过&#39;字符串,直到找到一个有内容的字符串,然后&#39;采取&#39;所有字符串,直到找到没有内容的字符串。

虽然@MarcinJuraszek指出,这将在没有内容的第一行之后停止,而不是删除列表末尾的那些。

为此,您可以使用以下内容:

IEnumerable<string> list  = sourceList.SkipWhile(source => !HasContent(source))
                                      .Reverse()
                                      .SkipWhile(source => !HasContent(source))
                                      .Reverse();

有点令人费解,但应该这样做。

答案 3 :(得分:2)

检查我刚才做的扩展方法:

public static class ListExtensions
{
    public static List<string> TrimList(this List<string> list)
    {
        int listCount = list.Count;
        List<string> listCopy = list.ToList();
        List<string> result = list.ToList();

        // This will encapsulate removing an item and the condition to remove it.
        // If it removes the whole item at some index, it return TRUE.
        Func<int, bool> RemoveItemAt = index =>
        {
            bool removed = false;

            if (string.IsNullOrEmpty(listCopy[index]) || string.IsNullOrWhiteSpace(listCopy[index]))
            {
                result.Remove(result.First(item => item == listCopy[index]));
                removed = true;
            }

            return removed;
        };

        // This will encapsulate the iteration over the list and the search of 
        // empty strings in the given list
        Action RemoveWhiteSpaceItems = () =>
        {
            int listIndex = 0;

            while (listIndex < listCount && RemoveItemAt(listIndex))
            {
                listIndex++;
            }
        };

        // Removing the empty lines at the beginning of the list
        RemoveWhiteSpaceItems();

        // Now reversing the list in order to remove the 
        // empty lines at the end of the given list
        listCopy.Reverse();
        result.Reverse();

        // Removing the empty lines at the end of the list
        RemoveWhiteSpaceItems();

        // Reversing again in order to recover the right list order.
        result.Reverse();

        return result;
    }
}

......及其用法:

List<string> list = new List<string> { "\t", " ", "    ", "a", "b", "\t", "         ", " " };

// The TrimList() extension method will return a new list without
// the empty items at the beginning and the end of the sample list!
List<string> trimmedList = list.TrimList();

答案 4 :(得分:2)

此方法修改原始 List<string>,而不是使用所需属性创建新对象:

static void TrimEmptyLines(List<string> listToModify)
{
  if (listToModify == null)
    throw new ArgumentNullException();

  int last = listToModify.FindLastIndex(HasContent);
  if (last == -1)
  {
    // no lines have content
    listToModify.Clear();
    return;
  }
  int count = listToModify.Count - last - 1;
  if (count > 0)
    listToModify.RemoveRange(last + 1, count);

  int first = listToModify.FindIndex(HasContent);
  if (first > 0)
    listToModify.RemoveRange(0, first);
}

在此代码中,HasContent是原始问题的方法。对于委托,可以使用像lambda这样的匿名函数。

答案 5 :(得分:1)

以下代码可满足您的需求:

List<string> lines = new List<string> {"   \n\t", " ", "aaa", "  \t\n", "bb", "\n", " "};
IEnumerable<string> filtered = lines.SkipWhile(String.IsNullOrWhiteSpace).Reverse().SkipWhile(String.IsNullOrWhiteSpace).Reverse();

它将列表反转两次,因此如果性能是关键,它可能不是理想的解决方案。

答案 6 :(得分:-1)

您可以使用isnullorwhitespace进行检查:请参阅下面的示例。

        List<string> lines = new List<string>();
        lines.Add("         ");
        lines.Add("one");
        lines.Add("two");
        lines.Add("");
        lines.Add("");
        lines.Add("five");
        lines.Add("");
        lines.Add("       ");
        lines.RemoveAll(string.IsNullOrWhiteSpace);

答案 7 :(得分:-1)

List<string> name = new List<string>();
name.Add("              ");
name.Add("rajesh");
name.Add("raj");
name.Add("rakesh");
name.Add("              ");
for (int i = 0; i < name.Count(); i++)
{
  if (string.IsNullOrWhiteSpace(Convert.ToString(name[i])))
  {
    name.RemoveAt(i);
  }
}

答案 8 :(得分:-2)

关于构建代码,我猜您的行既不包含空格也不包含制表符,因此您可以将foreach替换为

if(line.Contains(' ') || line.Contains('\t'))
   return false;
return true;

答案 9 :(得分:-2)

List<string> name = new List<string>();
name.Add("              ");
name.Add("rajesh");
name.Add("raj");
name.Add("rakesh");
name.Add("              ");

name.RemoveAt(0);
name.RemoveAt(name.Count() - 1);