1

まず、これはおそらくXY問題です。申し訳ありません。

ファイルからファイルテーブルをロードし、それをメモリ内のファイルツリーに配置しています。ツリー内のノードは、ツリー内のディレクトリ/ファイルを表します。現在、ノードごとに2つのデータ構造を使用しています。その結果、コレクションに挿入するために読み込み時間が顕著になり、文字列データを複製して各ノードを2回参照するためにメモリ使用量が増えます。ツリーは一度ロードされ、その後は変更されません。

すべてのノードには、ソートされた子ノードにアクセスするためのリストと、名前で子ノードにアクセスするための辞書があります。リストは、パフォーマンス上の理由から遅延ソートされています。SortedDictionaryは、子のあるノードを子のないノードの上にソートする必要があるため、使用要件に適合しません。したがって、IComparerを渡すだけでは不十分です。2つのノードの両方に子がある/ない場合、それらは辞書式にソートされます(OrdinalIgnoreCase)。

.netに私のニーズを満たすデータ構造はありますか?

さらに、ディクショナリに挿入するときにキーのハッシュを提供し、後でディクショナリからバケットの一部を取得する方法はありますか(つまり、GetValuesByHash(int hashValue)は、対応するキーが指定されたハッシュを持つすべての値を生成します) ?私が読んでいるファイルテーブルには、ファイルパス全体のハッシュ値がすでに含まれています(私が行っている別のことに適用できます)。現在、辞書は理由もなくそれらを再計算しています。

カスタム比較ツールと一緒に{Hash、Node}を含む独自のカスタムキーを定義することでソリューションをまとめることができると思いますが、それは本当に醜いようで、同じハッシュを共有するノードのバケットを取得することはできません。どちらかといえば、それでも間違ったデータ構造を使用しているように感じます。

私はすでに「c#dictionary get hash」を他のいくつかのクエリと一緒にグーグルで検索しましたが、現時点では、同様の質問は見ていません。

全体として、次のプロパティを持つデータ構造(おそらく辞書に関連する)を探します。

  • containsKeyOfHash()、Get(hash):ファイル名ハッシュ->ファイルエントリ記述子
  • containsKey()、Get(key):ファイル名->ファイルエントリ記述子
  • Add(string fileName、Entry entry、int hash = gethash(fileName))
  • エントリは次のように並べ替えられます。

        m_children.Sort(
           (a, b) => {
              bool aHasChildren = a.HasChildren;
              bool bHasChildren = b.HasChildren;
              if (aHasChildren && !bHasChildren)
                 return 1;
              if (!aHasChildren && bHasChildren)
                 return -1;
              else
                 return -String.Compare(a.m_resourceName, b.m_resourceName, StringComparison.OrdinalIgnoreCase);
           }
        );
    
  • すべての子ノードは、上記のソートされた順序で取得できます。現在、ChildrenSortedプロパティとChildrenUnsortedプロパティがあります。ChildrenSortedプロパティでは、並べ替えが原因でパフォーマンスが低下する可能性がありますが、ChildrenUnsortedプロパティでは発生しません。

さらに悪いことに、私の解決策は、独自の辞書のようなクラスを作成することだと思います。辞書からキーを削除する必要がないので、難しいことではありません。でも、そんなことは避けたいと思います。

私のノードの実装は、http: //pastie.org/5547925で見ることができます。

ありがとう!

4

2 に答える 2

1

あなたの解決策はすでにかなり良いと思います。ここにいくつかの考えがあります:

  1. ソートされ、キーによる高速アクセスの両方を備えたコレクションの場合、私はツリーデータ構造しか考えられません。アイテムごとに1つのオブジェクトを割り当てるデータ構造はおそらく必要ありません。おそらく、すべてのアイテムが単一の配列に配置されている一種のヒープが最適です。最初にすべての子を並べ替えてから、それらにデータを入力することで、その構造を非常に効率的に構築できると思います(現在行っているように)。
  2. すべてのデータをそのような単一のツリーに詰め込むことを検討してください。これにより、ノードごとのオーバーヘッドがほとんど節約されます(それ自体が子オブジェクトを持つコレクションなど)。キーは、ノードへの「パス」であり、効率的な形式で保存されます。"d1\d2\filename"またはのようなパスにすることができますstring[]

ポイント(2)は、RDBMSがそれを行う方法です。

于 2012-12-18T16:09:20.563 に答える
0

ラムダを`IComparerにSortedDictionary入れるだけで使用できます。Sort()

public class MyComparer : IComparer, IComparer<MyNode>
{
    public int Compare(object x, object y)
    {
        return Compare(x as MyNode, y as MyNode);
    }

    public int Compare(MyNode x, MyNode y)
    {
        if (ReferenceEquals(x, y))
        {
            return 0;
        }

        if (ReferenceEquals(x, null))
        {
            return -1;
        }

        if (ReferenceEquals(y, null))
        {
            return 1;
        }

        bool xHasChildren = x.HasChildren;
        bool yHasChildren = y.HasChildren;
        if (xHasChildren && !yHasChildren)
            return 1;
        if (!xHasChildren && yHasChildren)
            return -1;
        else
            return String.Compare(y.m_resourceName, x.m_resourceName, StringComparison.OrdinalIgnoreCase);
    }
}
于 2012-12-18T16:08:59.477 に答える