1

を実装するリストクラスがありますIEnumerable<T>
タイプ T は、一意の識別子として文字列メンバーを持つ複合クラスです。しかし、説明のために要素の型としてintだけを使用するだけで十分です。

複数のアイテムを 1 段左に移動したい。
例:
元のリスト: 0 , 1, 2, 3 , 4 , 5
ここで、すべての太字の項目 (0,3,4) を (可能な限り) 左に移動する必要があります。
結果リスト: 0 , 1, 3 , 4 , 2, 5

それを行うための良いアルゴリズムはありますか?多分LINQだけです。

編集:List<T>リストへの回答は大歓迎です。私のクラスには同様のメソッドがあります。(TylerOhlsen によるヒントに感謝します。)
Edit2: 1 つの選択された項目が別の選択された項目を通過してはなりません。

4

4 に答える 4

3

これは機能しているように見えます:

public static IEnumerable<T> MoveSelectedLeft<T>(
    this IEnumerable<T> source,
    IEnumerable<int> indicesToMove /* must be in order! */)
{
    using (var itm = indicesToMove.GetEnumerator())
    {
        bool hasNextToMove = itm.MoveNext();
        int nextToMove = hasNextToMove ? itm.Current : -1;

        bool canMoveYet = false;
        T held = default(T);
        int currentIndex = 0;

        foreach (T t in source)
        {
            if (hasNextToMove && nextToMove == currentIndex)
            {
                hasNextToMove = itm.MoveNext();
                nextToMove = hasNextToMove ? itm.Current : -1;
                yield return t;
            }
            else
            {
                if (!canMoveYet)
                {
                    canMoveYet = true;
                }
                else
                {
                    yield return held;
                }
                held = t;
            }

            currentIndex++;
        }

        if (canMoveYet)
            yield return held;
    }
}

と呼ばれる

foreach (int i in new[] { 0,1,2,3,4,5 }.MoveSelectedLeft(new[] { 0,3,4 }))
{
    Console.WriteLine(i);
}
于 2012-11-07T16:09:16.430 に答える
2

私は Linq の良い使い方を思いつきませんでしたが、単純なループ アルゴリズムを次に示します。ソート機能を思いつくことができれば、それはより良いでしょう。または、Linq Zipメソッドを見ることもできます。

IList<int> myList = new List<int>(new[] {0, 1, 2, 3, 4, 5});
IList<int> moveLeftList = new List<int>(new[] {0, 1, 3, 4});

//Go through the original list in order and remove
// all items from the move left list until you reach
// the first item that is not going to be moved left.
//Items removed are already as far left as they can be
// so they do not need to be moved left and can therefore
// be safely removed from the list to be moved.
foreach (int item in myList)
{
    int index = moveLeftList.IndexOf(item);

    if (index >= 0)
        moveLeftList.RemoveAt(index);
    else
        break;
}

foreach (int item in moveLeftList)
{
    int index = myList.IndexOf(item);

    //Dont move left if it is the first item in the list or it is not in the list
    if (index <= 0)
        continue;

    //Swap with this item with the one to its left
    myList.RemoveAt(index);
    myList.Insert(index-1, item);
}
于 2012-11-07T16:16:05.127 に答える
1

これには「Sort」関数を使用し、カスタム比較子を提供する必要があります。

この例を見てください。

于 2012-11-07T15:42:37.073 に答える
1

アルゴリズムの説明です。2要素のグループ (この場合は a ) の左にある要素を `temp 変数に 直接保存します。

一番左の要素から始めて、要素を 1 つずつ左に移動します。

tempグループが現在ある場所の右側に変数を配置します。

リンクされたリストを使用している場合は、より良い可能性があります。を削除して2、グループの右側に挿入します。

于 2012-11-07T15:39:10.823 に答える