HashSet 만들기 대소 문자를 구분하지 않음
HashSet 매개 변수가있는 메서드가 있습니다. 그리고 그 안에 대소 문자를 구분하지 않는 포함을 수행해야합니다.
public void DoSomething(HashSet<string> set, string item)
{
var x = set.Contains(item);
...
}
기존 HashSet을 대소 문자를 구분하지 않게 만드는 방법이 있습니까 (새로 만들지 마십시오)?
최고의 성능을 가진 솔루션을 찾고 있습니다.
편집하다
포함은 여러 번 호출 할 수 있습니다. 따라서 IEnumerable 확장은 네이티브 HashSet Contains 메서드보다 성능이 낮기 때문에 허용되지 않습니다.
해결책
내 질문에 대한 대답은 아니오이므로 불가능하므로 다음 방법을 만들고 사용했습니다.
public HashSet<string> EnsureCaseInsensitive(HashSet<string> set)
{
return set.Comparer == StringComparer.OrdinalIgnoreCase
? set
: new HashSet<string>(set, StringComparer.OrdinalIgnoreCase);
}
HashSet<T>
생성자는 사용자 정의에 건네 줄 수가 있습니다 과부하가 있습니다 IEqualityComparer<string>
. 이 중 일부는 이미 정적 StringComparer
클래스 에 정의되어 있으며 일부는 대소 문자를 무시합니다. 예를 들면 :
var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
set.Add("john");
Debug.Assert(set.Contains("JohN"));
.NET Framework를 생성 할 때이 변경을 수행해야합니다 HashSet<T>
. 하나가 존재하면 IEqualityComparer<T>
사용 중인 것을 변경할 수 없습니다 .
(당신이 어떤 전달하지 않는 경우 그냥 그래서 당신은 기본적으로 알고 IEqualityComparer<T>
받는 HashSet<T>
생성자)이 사용하는 EqualityComparer<T>.Default
대신.
편집하다
내 답변을 게시 한 후 질문이 변경된 것 같습니다. 당신이 사건을해야 할 경우 를 구분 기존의 경우 검색 민감 HashSet<string>
, 당신은 선형 검색을 수행해야합니다 :
set.Any(s => string.Equals(s, item, StringComparison.OrdinalIgnoreCase));
이 문제를 해결할 방법이 없습니다.
대소 문자를 구분하지 않는 방식으로 동작하도록 대소 문자를 구분하는 HashSet (또는 사전)을 마술처럼 만들 수 없습니다.
HashSet
대소 문자를 구분하지 않기 위해 수신 에 의존 할 수 없다면 함수 내에서 하나를 다시 만들어야합니다 .
가장 간결한 코드- 기존 집합의 생성자 를 사용 합니다.
var insensitive = new HashSet<string>(
set, StringComparer.InvariantCultureIgnoreCase);
복사 HashSet
는 모든 항목을 살펴 보는 것만 큼 비싸므로 함수가 검색 만 수행하는 경우 모든 항목을 반복하는 것이 더 저렴합니다 (O (n)). 함수가 대소 문자를 구분하지 않는 단일 검색을 위해 여러 번 호출 된 경우 HashSet
대신 적절 하게 전달해야 합니다.
는 HashSet
빠르게 해시 기능과 평등의 비교에 따라 요소를 찾을 수 있도록 설계되었습니다. 당신이 요구하는 것은 실제로 "다른"조건과 일치하는 요소를 찾는 것입니다. 비교 용으로 Set<Person>
만 사용 하는 객체가 Person.Name
있고 주어진 값이있는 요소를 찾아야 한다고 가정 해보 십시오 Person.Age
.
요점은 일치하는 요소를 찾기 위해 세트의 내용을 반복해야한다는 것입니다. 이 작업을 자주 수행하려는 경우 대소 문자를 구분하지 않는 비교기를 사용하는 경우 다른 세트를 만들 수 있지만이 그림자 세트가 원본과 동기화되어 있는지 확인해야합니다.
지금까지의 답변은 본질적으로 위의 변형이며, 근본적인 문제를 명확히하기 위해 이것을 추가하려고 생각했습니다.
이 확장 방법이 있다고 가정합니다.
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
return new HashSet<T>(source);
}
이것을 사용할 수 있습니다.
set = set.Select(n => n.ToLowerInvariant()).ToHashSet();
또는 다음과 같이 할 수 있습니다.
set = new HashSet(set, StringComparer.OrdinalIgnoreCase);
//or InvariantCultureIgnoreCase or CurrentCultureIgnoreCase
의 생성자는 동등성이 결정되는 방식을 재정 의 HashSet
할 수있는 대안 IEqualityComparer
을 취할 수 있습니다. 여기 에서 생성자 목록을 참조 하십시오 .
The class StringComparer
contains a bunch of static instances of IEqualityComparers
for strings. Particularly, you're probably interested in StringComparer.OrdinalIgnoreCase
. Here is the documentation of StringComparer
.
Note that another constructor takes in an IEnumerable
, so you can construct a new HashSet
from your old one, but with the IEqualityComparer
.
So, all together, you want to convert your HashSet
as follows:
var myNewHashSet = new HashSet(myOldHashSet, StringComparer.OrdinalIgnoreCase);
If you want to leave the original, case-sensitive version in place, you could just query it with linq with case insensitivity:
var contains = set.Any(a => a.Equals(item, StringComparison.InvariantCultureIgnoreCase));
You can now use
set.Contains(item, StringComparer.OrdinalIgnoreCase);
without needing to re-create you HashSet
참고URL : https://stackoverflow.com/questions/16922435/make-hashsetstring-case-insensitive
'program story' 카테고리의 다른 글
rabbitmq 관리 플러그인 (rabbitmq-plugins) 설치 방법 (0) | 2020.12.04 |
---|---|
네임 스페이스 'std'의 'vector'가 유형 이름을 지정하지 않습니다. (0) | 2020.12.04 |
XPath 표현식에서 Regex를 사용할 수 있습니까? (0) | 2020.12.04 |
요소의 상단 위치를 얻는 방법은 무엇입니까? (0) | 2020.12.04 |
printf를 사용하여 널이 아닌 문자열을 어떻게 인쇄합니까? (0) | 2020.12.04 |