1

我有一个实现的列表类IEnumerable<T>
Type T 是一个复杂的类,以字符串成员作为唯一标识符。但是仅将int作为元素类型进行解释就足够了。

我想将多个项目向左移动一步。
示例:
原始列表:0 , 1, 2, 3 , 4 , 5
现在所有粗体项目 (0,3,4) 应向左移动(尽可能)。
结果列表:0 , 1, 3 , 4 , 2, 5

有没有好的算法来做到这一点?也许只是使用 LINQ。

编辑:List<T>欢迎回答列表。我的班级有类似的方法。(感谢 TylerOhlsen 的提示。)
Edit2:一个选定的项目不应通过另一个选定的项目。

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

这是一个算法的描述。将元素直接存储到元素组的左侧(在本例中为 a 2)在 `temp 变量中。

从最左边的元素开始,将元素向左 1 1 移动。

temp变量放在组现在所在位置的右侧。

如果您使用的是链表,它会更好。您只需2从它所在的位置删除它,并将其插入到组的右侧。

于 2012-11-07T15:39:10.823 回答
1

您应该为此使用“排序”功能并提供自定义比较器。

看看这个例子

于 2012-11-07T15:42:37.073 回答