StringSplitOptions.RemoveEmptyEntries не работает, как рекламируется

Я сталкивался с этим несколько раз в прошлом и, наконец, решил выяснить, почему.

StringSplitOptions.RemoveEmptyEntries предполагает, что он удаляет пустые записи.

Так почему же этот тест не пройден?

var tags = "One, Two, , Three,   Foo Bar, , Day    , ";

var tagsSplit = tags.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
    .Select(s => s.Trim());

tagsSplit.ShouldEqual(new string[] {
    "One",
    "Two",
    "Three",
    "Foo Bar",
    "Day"
});

Результат:

  Values differ at index [2]
  Expected string length 5 but was 0. Strings differ at index 0.
  Expected: "Three"
  But was:  <string.Empty>

Поэтому происходит сбой, потому что вместо "Three" у нас есть пустая строка - именно то, что StringSplitOptions.RemoveEmptyEntries должно предотвратить.

Ответы

Ответ 1

Скорее всего, потому что вы изменили строку после разделения. Вы RemoveEmptyEntries значения после их разделения, RemoveEmptyEntries не считает строку " " пустой.

Следующее будет достигать того, что вы хотите, в основном создавая собственные пустые пустые элементы:

var tagsSplit = tags.Split(',').
                  Select(tag => tag.Trim()). 
                  Where( tag => !string.IsNullOrEmpty(tag));

Ответ 2

Смежные разделители дают элемент массива, содержащий пустой string (""). Значения перечисления StringSplitOptions указывают содержит ли элемент массива, который содержит пустую строку, в возвращенный массив.

" " по определению не пуст (на самом деле это пробел), поэтому он не удаляется из результирующего массива.

Если вы используете .net framework 4, вы можете обойти это, используя string.IsNullOrWhitespace:

var tagsSplit = tags.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                .Where(x => !string.IsNullOrWhiteSpace(x))
                .Select(s => s.Trim());

Ответ 3

RemoveEmptyEntries не означает пробел.
Ваша строка ввода включает в себя множество "пробелов". Вы должны заметить, что "пространство" не пустое. В компьютере пространство представляет собой специальный код ASCII. поэтому код:

var tagsSplit = tags.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
    .Select(s => s.Trim());

означает:

  • Разделите ввод на ',' и удалите пустую запись, а не укажите пробел. Так вы получили массив с некоторыми элементами пространства.
  • Затем вы выполняете обрезку для каждого из элементов. Элементы пространства становятся пустыми.

Вот почему ты это понял.

Ответ 4

Try

var tagsSplit = tags.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);

Это будет запятнать запятой и пробелом и устранить пустые строки.

Ответ 5

Я также искал чистый способ исключить пробельные записи во время разделения, но поскольку все параметры выглядели как-то вроде обходных решений, я решил исключить их при переходе по массиву.

string[] tagsSplit = tags.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tag in tagsSplit.Where(t => !string.IsNullOrWhiteSpace(t))) { }

Я думаю, что это выглядит чище и - в качестве бонуса - .Split(...).ToArray() может быть пропущено. Конечно, это вариант, когда вы можете зацикливать сразу после разделения и не хранить записи для последующего использования.

Ответ 6

var tagsSplit = tags.Split(',')
                    .Where(str => str != String.IsNullOrWhiteSpace(str))
                    .Select(s => s.Trim());

Ответ 7

Поскольку это очень распространенная необходимость, я пошел дальше и обернул самый популярный ответ в метод расширения строки:

public static IEnumerable<string> Split_RemoveWhiteTokens(this string s, params char[] separator)
{
    return s.Split(separator).
          Select(tag => tag.Trim()).
          Where(tag => !string.IsNullOrEmpty(tag));
}

Чтобы разделить на ',', как другие примеры, используйте так: var result = yourString.Split_RemoveWhiteTokens (',')

Обратите внимание, что тип возвращаемого значения - IEnumerable, поэтому вы можете выполнять дополнительные запросы LINQ непосредственно к возвращаемому результату. Вызовите .ToList(), если вы хотите привести результат к списку.

Ответ 8

Value.Split(новый char [] {'/'}, StringSplitOptions.RemoveEmptyEntries);

Это будет разбито на Slash. Он работает отлично!