12

2つの異なる構成ファイルから読み取っている要素/キーのセットがあります。したがって、キーは同じでも、それぞれに異なる値が関連付けられている場合があります。

それらをソート順にリストしたいと思います。私に何ができる ?クラスで試しましSortedListたが、キーの重複は許可されていません。

どうすればいいですか?

たとえば、キー1、2、3の要素が3つあるとします。次に、キー2を持つ要素をもう1つ取得します(ただし、値は異なります)。次に、新しいキーを既存のキー2の後、3の前に挿入します。キー2の要素が再び見つかった場合は、最後に追加されたキー2の後に挿入する必要があります。

.NET2.0を使用していることに注意してください

4

10 に答える 10

12

私はこのタイプのものにLINQを使用することを好みます:

using System.Linq;

...

var mySortedList = myList.Orderby(l => l.Key)
                         .ThenBy(l => l.Value);

foreach (var sortedItem in mySortedList) {
    //You'd see each item in the order you specified in the loop here.
}

注: これを行うには、.NET 3.5 以降を使用する必要があります。

于 2010-08-05T12:24:40.773 に答える
9

必要なのは、カスタムIComparerを使用した Sort 関数です。あなたが持っているのは、ソートを使用するときのデフォルトの icomparer です。これにより、フィールド値がチェックされます。

カスタム IComparer を作成する場合 ( Icomparableインターフェイスを実装することにより、クラスでこれを行います)。つまり、オブジェクトは、並べ替えたリスト内の他のすべてのオブジェクトに対して自分自身をチェックします。

これは関数によって行われます。(インターフェイスを参照するときにVSが実装することを心配しないでください

public class  ThisObjectCLass : IComparable{

    public int CompareTo(object obj) {
            ThisObjectCLass something = obj as ThisObjectCLass ;
            if (something!= null) 
                if(this.key.CompareTo(object.key) == 0){
                //then:
                   if .....
                }
                else if(this.value "is more important then(use some logic here)" something.value){
                 return 1
                }
                else return -1
            else
               throw new ArgumentException("I am a dumb little rabid, trying to compare different base classes");
        }
}

より良い情報については、上記のリンクをお読みください。

私は最初にこれを自分で理解するのに苦労したことを知っているので、さらに助けが必要な場合はコメントを追加してください。詳しく説明します

于 2010-08-05T12:34:21.010 に答える
7

を作成することでそれを行いましたSortedList<int, List<string>>。重複するキーが見つかったら、SortedList オブジェクトに既に存在するキーに関連付けられた既存のリストに値を挿入するだけです。このようにして、特定のキーの値のリストを取得できます。

于 2010-08-06T11:48:45.653 に答える
5

独自の比較クラスを使用してください。 ソートされたリストのキーが整数の場合、たとえば次の比較子を使用できます。

public class DegreeComparer : IComparer<int>
{
    #region IComparer<int> Members

    public int Compare(int x, int y)
    {
        if (x < y)
            return -1;
        else
            return 1;
    }

    #endregion
}

int キーと文字列値を使用して新しい SortedList をインスタンス化するには、次を使用します。

var mySortedList = new SortedList<int, string>(new DegreeComparer());
于 2012-10-02T14:22:23.677 に答える
2

等しいキーを持つ要素の順序をあまり気にしない場合は、すべてをリストに追加してから、キーで並べ替えます。

static void Main(string[] args)
{
   List<KeyValuePair<int, MyClass>> sortedList = 
      new List<KeyValuePair<int, MyClass>>() {
         new KeyValuePair<int, MyClass>(4, new MyClass("four")), 
         new KeyValuePair<int, MyClass>(7, new MyClass("seven")),
         new KeyValuePair<int, MyClass>(5, new MyClass("five")),
         new KeyValuePair<int, MyClass>(4, new MyClass("four-b")),
         new KeyValuePair<int, MyClass>(7, new MyClass("seven-b"))
      };
   sortedList.Sort(Compare);
}
static int Compare(KeyValuePair<int, MyClass> a, KeyValuePair<int, MyClass> b)
{
   return a.Key.CompareTo(b.Key);
}

後で挿入する項目を前に挿入した項目の後に配置したい場合は、挿入された順に並べ替えます。

class Sorter : IComparer<KeyValuePair<int, MyClass>>
{

static void Main(string[] args)
{
   List<KeyValuePair<int, MyClass>> sortedList = new List<KeyValuePair<int, MyClass>>();
   Sorter sorter = new Sorter();
   foreach (KeyValuePair<int, MyClass> kv in new KeyValuePair<int, MyClass>[] {
      new KeyValuePair<int, MyClass>(4, new MyClass("four")), 
      new KeyValuePair<int, MyClass>(7, new MyClass("seven")),
      new KeyValuePair<int, MyClass>(5, new MyClass("five")),
      new KeyValuePair<int, MyClass>(4, new MyClass("four-b")),
      new KeyValuePair<int, MyClass>(4, new MyClass("four-c")),
      new KeyValuePair<int, MyClass>(7, new MyClass("seven-b")) })
   {
      sorter.Insert(sortedList, kv);
   }
   for (int i = 0; i < sortedList.Count; i++)
   {
      Console.WriteLine(sortedList[i].ToString());
   }
}
void Insert(List<KeyValuePair<int, MyClass>> sortedList, KeyValuePair<int, MyClass> newItem)
{
   int newIndex = sortedList.BinarySearch(newItem, this);
   if (newIndex < 0)
      sortedList.Insert(~newIndex, newItem);
   else
   {
      while (newIndex < sortedList.Count && (sortedList[newIndex].Key == newItem.Key))
         newIndex++;
      sortedList.Insert(newIndex, newItem);
   }
}
#region IComparer<KeyValuePair<int,MyClass>> Members

public int Compare(KeyValuePair<int, MyClass> x, KeyValuePair<int, MyClass> y)
{
   return x.Key.CompareTo(y.Key);
}

#endregion
}

または、並べ替えられたリストのリストを作成できます。

static void Main(string[] args)
{
   SortedDictionary<int, List<MyClass>> sortedList = new SortedDictionary<int,List<MyClass>>();
   foreach (KeyValuePair<int, MyClass> kv in new KeyValuePair<int, MyClass>[] {
      new KeyValuePair<int, MyClass>(4, new MyClass("four")), 
      new KeyValuePair<int, MyClass>(7, new MyClass("seven")),
      new KeyValuePair<int, MyClass>(5, new MyClass("five")),
      new KeyValuePair<int, MyClass>(4, new MyClass("four-b")),
      new KeyValuePair<int, MyClass>(4, new MyClass("four-c")),
      new KeyValuePair<int, MyClass>(7, new MyClass("seven-b")) })
   {
      List<MyClass> bucket;
      if (!sortedList.TryGetValue(kv.Key, out bucket))
         sortedList[kv.Key] = bucket = new List<MyClass>();
      bucket.Add(kv.Value);
   }
   foreach(KeyValuePair<int, List<MyClass>> kv in sortedList)
   {
      for (int i = 0; i < kv.Value.Count; i++ )
         Console.WriteLine(kv.Value[i].ToString());
   }
}

上記の最初の例で行ったように、.NET 2.0 でリスト初期化子を使用できるかどうかはわかりませんが、リストにデータを入力する方法は知っているはずです。

于 2010-08-05T13:19:57.730 に答える
1

.NET は、安定した並べ替え(つまり、同等の要素が並べ替えられたときに相対的な順序を維持することを意味します)を大幅にサポートしていません。List.BinarySearchただし、カスタム(キーターゲットIComparer<T>以下の場合は -1 を返し、大きい場合は +1 を返す)を使用して、独自の stable-sorted-insert を作成できます。

は安定した並べ替えではないことに注意してください。そのList.Sortため、独自の安定したクイック並べ替えルーチンを作成するか、挿入並べ替えを使用して最初にコレクションにデータを入力する必要があります。

于 2010-08-05T12:32:22.653 に答える
0

.NET 2.0では、次のように書くことができます。

List<KeyValuePair<string, string>> keyValueList = new List<KeyValuePair<string, string>>();

// Simulate your list of key/value pair which key could be duplicate
keyValueList.Add(new KeyValuePair<string,string>("1","One"));
keyValueList.Add(new KeyValuePair<string,string>("2","Two"));
keyValueList.Add(new KeyValuePair<string,string>("3","Three"));

// Here an entry with duplicate key and new value
keyValueList.Add(new KeyValuePair<string, string>("2", "NEW TWO")); 

// Your final sorted list with one unique key
SortedList<string, string> sortedList = new SortedList<string, string>();

foreach (KeyValuePair<string, string> s in keyValueList)
{
    // Use the Indexer instead of Add method
    sortedList[s.Key] = s.Value;
}

出力:

[1, One]
[2, NEW TWO]
[3, Three]
于 2010-08-06T12:10:20.527 に答える
0

キーごとに複数の値を格納できるNameValueCollectionクラスを検討しましたか? たとえば、次のようにすることができます。

    NameValueCollection nvc = new NameValueCollection();
    nvc.Add("1", "one");
    nvc.Add("2", "two");
    nvc.Add("3", "three");

    nvc.Add("2", "another value for two");
    nvc.Add("1", "one bis");

そして、あなたが持つことができる値を取得するには:

    for (int i = 0; i < nvc.Count; i++)
    {
        if (nvc.GetValues(i).Length > 1)
        {
            for (int x = 0; x < nvc.GetValues(i).Length; x++)
            {
                Console.WriteLine("'{0}' = '{1}'", nvc.GetKey(i), nvc.GetValues(i).GetValue(x));
            }
        }
        else
        {
            Console.WriteLine("'{0}' = '{1}'", nvc.GetKey(i), nvc.GetValues(i)[0]);
        }

    }

出力を与える:

「1」=「1」

'1' = '1 ビス'

「2」=「2」

'2' = '2 の別の値'

「3」=「3」

于 2010-08-05T13:45:34.423 に答える
0

これはどう

        SortedList<string, List<string>> sl = new SortedList<string, List<string>>();

        List<string> x = new List<string>();

        x.Add("5");
        x.Add("1");
        x.Add("5");
        // use this to load  
        foreach (string z in x)
        {
            if (!sl.TryGetValue(z, out x))
            {
                sl.Add(z, new List<string>());
            }

            sl[z].Add("F"+z);
        }
        // use this to print 
        foreach (string key in sl.Keys)
        {
            Console.Write("key=" + key + Environment.NewLine);

            foreach (string item in sl[key])
            {
                Console.WriteLine(item);
            }
        }
于 2011-04-09T00:18:11.703 に答える
0

コンピューターを動かすチェスゲームのコンセプトに似たゲームを設計していたときに、同様の問題がありました。複数の駒が動く可能性が必要だったので、複数のボード状態が必要でした。各 BoardState は、ピースの位置に基づいてランク付けする必要がありました。議論を簡単にするために、私のゲームはゼロとクロスで、私はゼロで、コンピューターはクロスであるとします。ボードの状態がゼロの列で 3 を示している場合、これは私にとって最良の状態です。クロスの列で 3 を示している場合、これは私にとって最悪の状態であり、コンピューターにとっては最良の状態です。ゲーム中にどちらか一方に有利な他の状態があり、さらに引き分けになる複数の状態があるため、ランクスコアが等しい場合にランク付けするにはどうすればよいですか。

私の比較クラス:

Class ByRankScoreComparer
    Implements IComparer(Of BoardState)

    Public Function Compare(ByVal bs1 As BoardState, ByVal bs2 As BoardState) As Integer Implements IComparer(Of BoardState).Compare
        Dim result As Integer = bs2.RankScore.CompareTo(bs1.RankScore) 'DESCENDING order
        If result = 0 Then
            result = bs1.Index.CompareTo(bs2.Index)
        End If
        Return result
    End Function
End Class

私の宣言:

Dim boardStates As SortedSet(Of BoardState)(New ByRankScoreComparer)

私のボードステートの実装:

Class BoardState
    Private Shared BoardStateIndex As Integer = 0
    Public ReadOnly Index As Integer
    ...
    Public Sub New ()
        BoardStateIndex += 1
        Index = BoardStateIndex
    End Sub
    ...
End Class

ご覧のとおり、RankScores は降順で維持され、同じランクスコアを持つ 2 つの状態は、常により大きなインデックスが割り当てられているため、後の状態が一番下に移動し、重複が可能になります。また、比較子を使用する boardStates.Remove(myCurrentBoardState) を安全に呼び出すこともできます。比較子は、削除するオブジェクトを見つけるために 0 値を返す必要があります。

于 2014-04-24T00:06:56.367 に答える