문제

나는 본질적으로 이름 값 쌍의 들쭉날쭉 한 배열이 있습니다. 이것으로부터 고유 한 이름 값 세트를 생성해야합니다. 들쭉날쭉 한 배열은 약 86,000 x 11 값입니다. 이름 값 쌍 (단일 문자열 "이름 = value"또는 Specialized Class와 같은 특수 클래스)을 저장하는 방법은 중요하지 않습니다.
추가 정보: 40 개의 별개의 이름과 더 많은 수의 별개의 값이 있습니다.

C# 및 .NET 2.0을 사용하고 있습니다 (성능이 너무 나쁘기 때문에 전체 제지 배열을 SQL 데이터베이스로 밀고 선택하는 것이 더 낫다고 생각합니다).

아래는 다음을 사용하는 현재 코드입니다.

List<List<KeyValuePair<string,string>>> vehicleList = retriever.GetVehicles();
this.statsLabel.Text = "Unique Vehicles: " + vehicleList.Count;

Dictionary<KeyValuePair<string, string>, int> uniqueProperties = new Dictionary<KeyValuePair<string, string>, int>();
foreach (List<KeyValuePair<string, string>> vehicle in vehicleList)
{
    foreach (KeyValuePair<string, string> property in vehicle)
    {
        if (!uniqueProperties.ContainsKey(property))
        {
            uniqueProperties.Add(property, 0);
        }
    }
}
this.statsLabel.Text += "\rUnique Properties: " + uniqueProperties.Count;
도움이 되었습니까?

해결책

0.34 초 안에 실행됩니다 9 분 이상

문제는 keyvaluepair structs를 비교할 때입니다. 비교 대상을 작성하고 사전에 인스턴스를 전달하여 주변에서 작업했습니다.

내가 결정할 수있는 것에서 keyvaluepair.gethashCode ()는 해시 코드를 반환합니다. Key 객체 (이 예에서 가장 고유 한 객체).

사전은 각 항목의 추가 (및 확인)를 추가 (및 확인)에 따라 Equals 및 gethashcode 함수를 모두 사용하지만 해시 코드가 덜 고유 할 때 평등 함수에 의존해야합니다.

보다 독특한 gethashcode 함수를 제공함으로써, 그것은 동등한 기능을 훨씬 덜 자주 발췌합니다. 또한 덜 고유 한 값을 덜 고유 한 값을 비교하기 위해 평등 함수를 최적화했습니다.

86,000 * 고유 한 특성을 가진 11 개의 항목은 아래의 비교 객체를 사용하여 0.34 초 안에 실행됩니다 (비교 객체가 없으면 9 분 22 초가 소요됨)

도움이 되었기를 바랍니다 :)

    class StringPairComparer
        : IEqualityComparer<KeyValuePair<string, string>>
    {
        public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
        {
            return x.Value == y.Value && x.Key == y.Key;
        }
        public int GetHashCode(KeyValuePair<string, string> obj)
        {
            return (obj.Key + obj.Value).GetHashCode();
        }
    }

편집하다: 단지 하나의 문자열이라면 (keyvaluepair 대신, String = name+value)는 약 2 배 빠릅니다. 그것은 좋은 intresting 문제이고 나는 보냈습니다. faaaaaar 너무 많은 시간 (그래도 조금 조용히 배웠 어)

다른 팁

각 키/값 쌍과 생성하는 고유 한 값 사이에 특정 상관 관계가 필요하지 않은 경우 Guid 만 사용할 수 있습니까? 이 문제는 현재 '키'가이 들쭉날쭉 한 배열에서 고유하지 않다고 가정합니다.

Dictionary<System.Guid, KeyValuePair<string, string>> myDict 
   = new Dictionary<Guid, KeyValuePair<string, string>>();


foreach of your key values in their current format
   myDict.Add(System.Guid.NewGuid(), new KeyValuePair<string, string>(yourKey, yourvalue))

필요한 것을 저장하는 것처럼 들리지만 Guid와 원래의 의미 사이에 의미 론적 관계가 없기 때문에 어떻게 데이터를 철회 할 것인지 모르겠습니다.

질문에 더 많은 정보를 제공 할 수 있습니까?

keyvaluepair를 래퍼 클래스로 사용한 다음 세트를 만들기 위해 사전을 만듭니다. 또는 평등과 gethashcode를 무시하는 자신의 래퍼를 구현하십시오.

Dictionary<KeyValuePair, bool> mySet;

for(int i = 0; i < keys.length; ++i)
{
    KeyValuePair kvp = new KeyValuePair(keys[i], values[i]);
    mySet[kvp] = true;
}

a를 사용하는 대신 Dictionary 확장하지 않는 이유는 무엇입니까? KeyedCollection<TKey, TItem>? 문서에 따르면 :

키가 값에 포함 된 컬렉션의 추상 기본 클래스를 제공합니다.

그런 다음을 무시해야합니다 protected TKey GetKeyForItem(TItem item) 기능. 하이브리드 사이입니다 IList<T> 그리고 IDictionary<TKey, TValue> 나는 그것이 매우 빠를 가능성이 높다고 생각합니다.

어때요 :

Dictionary<NameValuePair,int> hs = new Dictionary<NameValuePair,int>();
foreach (i in jaggedArray)
{
    foreach (j in i)
    {
        if (!hs.ContainsKey(j))
        {
            hs.Add(j, 0);
        }
    }
}
IEnumerable<NameValuePair> unique = hs.Keys;

물론 C# 3.0, .NET 3.5를 사용하는 경우 :

var hs = new HashSet<NameValuePair>();
hs.UnionWith(jaggedArray.SelectMany(item => item));

트릭을 할 것입니다.

코드를 프로파일 링 했습니까? Foreach 루프가 병목 현상이 아니며 Retriver.getvehicles ()가 아닌가?

나는 리트리버를 가짜로 만들고 86.000 x 11 값을 반환하도록하는 작은 테스트 프로젝트를 만들었습니다. 첫 번째 시도는 5 초에 실행되어 포함 된 데이터가 생성되었습니다.

첫 번째 키가 "0#0"이고 마지막 "85999#10"인 키와 값 모두에 대해 동일한 값을 사용했습니다.

그런 다음 Guids로 전환했습니다. 동일한 결과.

그런 다음 다음과 같이 키를 더 길게 만들었습니다.

        var s = Guid.NewGuid().ToString();
        return s + s + s + s + s + s + s+ s + s + s;

이제 거의 10 초가 걸렸습니다.

그런 다음 열쇠를 미친 듯이 길게 만들고 메모리 예외를 얻지 못했습니다. 내 컴퓨터에 스왑 파일이 없으므로 즉시이 예외를 얻었습니다.

열쇠는 얼마나 걸립니까? 가상 메모리 소비가 성능 저하의 이유입니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top