Определите, содержит ли HashSet<String> другую строку в регистре

У меня есть большой набор строк, в том числе много дубликатов. Важно, чтобы все дубликаты имели одинаковый корпус. Так что этот набор не пройдёт тест:

String[] strings = new String[] { "a", "A", "b", "C", "b" };

.... но этот тест пройдет

String[] strings = new String[] { "A", "A", "b", "C", "b" };

Как я перебираю каждую строку в stringsкак моя программа видит это A является регистронезависимым дубликатом a (и таким образом потерпеть неудачу), но разрешить дубликат b через?

3 ответа

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

После сборки, если два набора имеют разные размеры (Count) тогда должны быть некоторые элементы, которые равны при сравнении без учета регистра, но не равны при сравнении с учетом регистра.

Так что-то вроде:

public static bool AllDuplicatesSameCase(IEnumerable<string> input)
{
    var sensitive = new HashSet<String>(input, StringComparer.InvariantCulture);
    var insensitive = new HashSet<String>(input, 
          StringComparer.InvariantCultureIgnoreCase);
    return sensitive.Count == insensitive.Count;
}

Вы можете проверить каждую запись явно.

static bool DuplicatesHaveSameCasing(string[] strings)
{
  for (int i = 0; i < strings.Length; ++i)
  {
    for (int j = i + 1; j < strings.Length; ++j)
    {
      if (string.Equals(strings[i], strings[j], StringComparison.OrdinalIgnoreCase)
        && strings[i] != strings[j])
      {
        return false;
      }
    }
  }
  return true;
}

Комментарий: я решил использовать порядковое сравнение. Обратите внимание, что != Оператор использует порядковое и регистрозависимое сравнение. Это довольно тривиально, чтобы изменить это в какое-то культурно-зависимое сравнение.

И еще один вариант с использованием LINQ.

                    //Group strings without considering case
bool doesListPass = strings.GroupBy(s => s.ToUpper())
                    //Check that all strings in each group has the same case
                    .All(group => group.All(s => group.First() == s));

                    //Group strings without considering case
IEnumerable<string> cleanedList = strings.GroupBy(s => s.ToUpper())
                    //Check that all strings in each group has the same case
                    .Where(group => group.All(s => group.First() == s))
                    //Map all the "passing" groups to a list of strings 
                    .SelectMany(g => g.ToList());

Примечание. Вы можете использовать ToUpper() или ToUpperInvariant() в зависимости от ваших потребностей.

Другие вопросы по тегам