해시 세트에 비교기를 사용하는 방법
-
06-07-2019 - |
문제
또 다른 질문의 결과로 여기서 물었습니다. 내 개체에 해시를 사용하고 싶습니다.
문자열이 포함 된 객체와 소유자에 대한 참조를 만들 것입니다.
public class Synonym
{
private string name;
private Stock owner;
public Stock(string NameSynonym, Stock stock)
{
name=NameSynonym;
owner=stock
}
// [+ 'get' for 'name' and 'owner']
}
비교가 필요하다는 것을 이해하지만 전에는 사용하지 않았습니다. 별도의 클래스를 만들어야합니까? 처럼:
public class SynonymComparer : IComparer<Synonym>
{
public int Compare(Synonym One, Synonym Two)
{ // Should I test if 'One == null' or 'Two == null' ????
return String.Compare(One.Name, Two.Name, true); // Caseinsesitive
}
}
나는 다른 (독립) 클래스 대신 클래스 동의어의 일부인 함수 (또는 필요한 경우 중첩 클래스 [싱글 톤?])를 선호합니다. 이게 가능해?
사용법에 대해 : 이런 종류의 것을 사용한 적이 없으므로 클래스 동의어 내에 찾은 (문자열 이름 synononic) 기능을 작성해야한다고 가정하지만 어떻게해야합니까?
public class SynonymManager
{
private HashSet<SynonymComparer<Synonym>> ListOfSynonyms;
public SynonymManager()
{
ListOfSymnonyms = new HashSet<SynonymComparer<Synonym>>();
}
public void SomeFunction()
{ // Just a function to add 2 sysnonyms to 1 stock
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
ListOfSynonyms.Add(otherName);
Synonym otherName = new Synonym("Gen. Motors", stock);
ListOfSynonyms.Add(otherName);
}
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.??????(NameSynonym);
}
}
위의 코드에서는 '찾기'메소드를 구현하는 방법을 모르겠습니다. 어떻게해야하나요?
모든 도움이 감사하겠습니다 (PS가 구현 방법에 대한 내 아이디어가 완전히 잘못된 경우 PS는 저에게 알려 주시고 구현 방법을 알려주세요)
해결책
해시 세트는 필요하지 않습니다 IComparer<T>
- 필요합니다 IEqualityComparer<T>
, 와 같은
public class SynonymComparer : IEqualityComparer<Synonym>
{
public bool Equals(Synonym one, Synonym two)
{
// Adjust according to requirements.
return StringComparer.InvariantCultureIgnoreCase
.Equals(one.Name, two.Name);
}
public int GetHashCode(Synonym item)
{
return StringComparer.InvariantCultureIgnoreCase
.GetHashCode(item.Name);
}
}
그러나 현재 코드는 세트를 생성하기 때문에 컴파일됩니다. 비교 세트보다는 동의어.
또한, 나는 당신이 정말로 세트를 원한다고 생각하지 않습니다. 주어진 이름의 동의어를 찾을 수 있도록 사전이나 조회를 원한 것 같습니다.
public class SynonymManager
{
private readonly IDictionary<string, Synonym> synonyms = new
Dictionary<string, Synonym>();
private void Add(Synonym synonym)
{
// This will overwrite any existing synonym with the same name.
synonyms[synonym.Name] = synonym;
}
public void SomeFunction()
{
// Just a function to add 2 synonyms to 1 stock.
Stock stock = GetStock("General Motors");
Synonym otherName = new Synonym("GM", stock);
Add(otherName);
ListOfSynonyms.Add(otherName);
otherName = new Synonym("Gen. Motors", stock);
Add(otherName);
}
public Synonym Find(string nameSynonym)
{
// This will throw an exception if you don't have
// a synonym of the right name. Do you want that?
return synonyms[nameSynonym];
}
}
위의 코드에는 다양한 경우에 어떻게 행동하기를 원하는지에 대한 몇 가지 질문이 있습니다. 운동해야합니다 바로 그거죠 당신이 원하는 것.
편집 : 단일 동의어를 위해 여러 주식을 저장하려면 효과적으로 ~을 원한다 Lookup<string, Stock>
- 그러나 그것은 불변입니다. 당신은 아마도 가장 잘 보관하는 것입니다 Dictionary<string, List<Stock>>
; 각 문자열에 대한 주식 목록.
오류를 던지지 않는 관점에서 Find
, 당신은 봐야합니다 Dictionary.TryGetValue
키를 찾지 못한 경우 예외가 발생하지 않습니다 (및 키가 반환됩니다. ~였다 설립하다); 매핑 된 값은 OUT 매개 변수에서 "리턴"됩니다.
다른 팁
스크랩하는 것이 더 합리적이지 않을 것입니다 Synonym
전적으로 수업을하고 동의어 목록이 Dictonary
(또는 그런 것이 있다면 HashDictionary
) 문자열?
(나는 C# 유형에 익숙하지 않지만 이것이 일반적인 아이디어를 전달하기를 바랍니다)
내가 추천하는 대답 (편집, 이제 사건을 존중) :
IDictionary<string, Stock>> ListOfSynonyms = new Dictionary<string,Stock>>();
IDictionary<string, string>> ListOfSynForms = new Dictionary<string,string>>();
class Stock
{
...
Stock addSynonym(String syn)
{
ListOfSynForms[syn.ToUpper()] = syn;
return ListOfSynonyms[syn.ToUpper()] = this;
}
Array findSynonyms()
{
return ListOfSynonyms.findKeysFromValue(this).map(x => ListOfSynForms[x]);
}
}
...
GetStock("General Motors").addSynonym('GM').addSynonym('Gen. Motors');
...
try
{
... ListOfSynonyms[synonym].name ...
}
catch (OutOfBounds e)
{
...
}
...
// output everything that is synonymous to GM. This is mix of C# and Python
... GetStock('General Motors').findSynonyms()
// test if there is a synonym
if (input in ListOfSynonyms)
{
...
}
언제든지 LINQ를 사용하여 조회를 수행 할 수 있습니다.
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.SingleOrDefault(x => x.Name == NameSynomym);
}
그러나 대신 사전 사용을 고려해 보셨습니까? 단일 멤버를 추출하는 데 더 적합하다고 생각하며, 선택한 키를 기반으로 한 중복이 없음을 보장 할 수 있습니다.
조회 시간이 SingleordeFault인지 확신하지는 않지만 선형 (O (N))인지 확신합니다. 따라서 조회 시간이 중요하면 사전이 O (1) 조회 시간을 제공합니다.