Определите, содержит ли 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() в зависимости от ваших потребностей.