Как обрезать список, чтобы удалить предыдущие и последующие пустые строки?
какой самый простой способ сделать это?
результаты должны быть:
1: one
2: two
3:
4:
5: five
код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestLines8833
{
class Program
{
static void Main(string[] args)
{
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.TrimList();
}
}
public static class Helpers
{
public static List<string> TrimList(this List<string> list)
{
//???
}
}
}
8 ответов
Как насчет этого:
public static void TrimList(this List<string> list) {
while (0 != list.Count && string.IsNullOrEmpty(list[0])) {
list.RemoveAt(0);
}
while (0 != list.Count && string.IsNullOrEmpty(list[list.Count - 1])) {
list.RemoveAt(list.Count - 1);
}
}
обратите внимание, что подпись изменилась из вашего примера (тип возврата-void).
хорошо, теперь я понимаю желаемые результаты:
public static class Helpers
{
// Adjust this to use trimming, avoid nullity etc if you you want
private static readonly Predicate<string>
NonBlankLinePredicate = x => x.Length != 0;
public static List<string> TrimList(this List<string> list)
{
int start = list.FindIndex(NonBlankLinePredicate);
int end = list.FindLastIndex(NonBlankLinePredicate);
// Either start and end are both -1, or neither is
if (start == -1)
{
return new List<string>();
}
return list.GetRange(start, end - start + 1);
}
}
обратите внимание, что это не изменить существующий список - он возвращает новый список с желаемым содержанием. Было неясно, какое именно поведение вы хотите, учитывая, что вы дали методу тип возврата, но ваш образец вызывает его без использования результата. Лично я предпочитаю методы без побочных эффектов, хотя, возможно, стоит изменить название:)
попробуй это:
public static List<string> TrimList(this List<string> list)
{
return list.SkipWhile(l => String.IsNullOrEmpty(l)).Reverse().SkipWhile(l => String.IsNullOrEmpty(l)).Reverse();
}
старый вопрос я знаю, но вот метод расширения, который будет обрезать объекты с начала и конца коллекции на основе логического делегата с использованием Linq.
public static class IEnumerableExtensions
{
public static IEnumerable<T> Trim<T>( this IEnumerable<T> collection, Func<T, bool> trimCondition )
{
return collection.SkipWhile( trimCondition ).Reverse().SkipWhile( trimCondition ).Reverse();
}
}
пример для вашего случая:
lines.Trim(line => string.IsNullOrEmpty(line));
Если вы хотите удалить пустые строки, вы можете сделать что-то вроде этого...
lines = lines.Where(s => ! string.IsNullOrEmpty(s)).ToList();
обновление: извините, только что видел ваше редактирование, что вы хотите, чтобы внутренние пробелы остались.
в этом случае я бы просто метод расширения, как вы упомянули выше, я не думаю, что есть более простой способ сделать это.
нет ничего встроенного, чтобы сделать что-то конкретное, как это. Вы можете проверить элементы с начала и конца и удалить пустые строки. Чтобы минимизировать операции в списке (использование RemoveAt повторно для удаления первого элемента довольно неэффективно), сначала подсчитайте количество элементов для удаления, а затем используйте RemoveRange
метод, чтобы удалить их все сразу.
чтобы соответствовать тому, как вы используете метод в коде, расширение должно изменить список, а не возвращать новый список.
public static void TrimList(this List<string> list) {
int cnt = 0;
while (cnt < list.Count && list[cnt].Length == 0) cnt++;
if (cnt > 0) list.RemoveRange(0, cnt);
cnt = 0;
while (cnt < list.Count - 1 && list[list.Count - cnt - 1].Length == 0) cnt++;
if (cnt > 0) list.RemoveRange(list.Count - cnt, cnt);
}
int start = stringList.FindIndex((i => i.Trim() != ""));
int end = stringList.FindLastIndex((i => i.Trim() != ""));
List<string> range = new List<string>();
if(start != -1 && end != -1)
range = stringList.GetRange(start, (end - start + 1));
когда-нибудь старый добрый foreach бьет linq как с точки зрения читаемости, так и с точки зрения производительности:
public static List<string> TrimList(this List<string> list)
{
list.TrimListStart();
vat l = list.Reverse().ToList();
l.TrimListStart();
return l;
}
public void TrimListStart(this List<string> list)
{
foreach(var s in new List(list))
{
if(string.string.IsNullOrWhiteSpace(s))
{
list.Remove(s);
}
else
{
break;
}
}
}