泛型列表-在列表中移动一个项目

所以我有一个通用列表,一个 oldIndex和一个 newIndex值。

我想在 oldIndex移动项目,到 newIndex... 尽可能简单。

有什么建议吗?

注意

项目之间的项目应该结束在 (newIndex - 1)newIndex之间的 之前它被删除。

248554 次浏览

我认为:

// Makes sure item is at newIndex after the operation
T item = list[oldIndex];
list.RemoveAt(oldIndex);
list.Insert(newIndex, item);

或者:

// Makes sure relative ordering of newIndex is preserved after the operation,
// meaning that the item may actually be inserted at newIndex - 1
T item = list[oldIndex];
list.RemoveAt(oldIndex);
newIndex = (newIndex > oldIndex ? newIndex - 1, newIndex)
list.Insert(newIndex, item);

可以,但我没有 VS 可以检查。

var item = list[oldIndex];


list.RemoveAt(oldIndex);


if (newIndex > oldIndex) newIndex--;
// the actual index could have shifted due to the removal


list.Insert(newIndex, item);

将它们放入扩展方法中:

    public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
var item = list[oldIndex];


list.RemoveAt(oldIndex);


if (newIndex > oldIndex) newIndex--;
// the actual index could have shifted due to the removal


list.Insert(newIndex, item);
}


public static void Move<T>(this List<T> list, T item, int newIndex)
{
if (item != null)
{
var oldIndex = list.IndexOf(item);
if (oldIndex > -1)
{
list.RemoveAt(oldIndex);


if (newIndex > oldIndex) newIndex--;
// the actual index could have shifted due to the removal


list.Insert(newIndex, item);
}
}


}

将当前位于 oldIndex的项插入到 newIndex,然后删除原始实例。

list.Insert(newIndex, list[oldIndex]);
if (newIndex <= oldIndex) ++oldIndex;
list.RemoveAt(oldIndex);

必须考虑到要删除的项的索引可能会因插入而更改。

List < T > 。 RemoveAt ()和 List < T > 。 RemoveAt ()不返回要删除的项。

因此,你必须使用以下方法:

var item = list[oldIndex];
list.RemoveAt(oldIndex);
list.Insert(newIndex, item);

最简单的方法:

list[newIndex] = list[oldIndex];
list.RemoveAt(oldIndex);

剪辑

这个问题不是很清楚... ... 因为我们不关心 list[newIndex]条目放在哪里,我认为最简单的方法如下(有或没有扩展方法) :

    public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
T aux = list[newIndex];
list[newIndex] = list[oldIndex];
list[oldIndex] = aux;
}

这个解决方案是最快的,因为它不涉及列表插入/删除。

我知道您说过“通用列表”,但是您没有指定需要使用 名单(T)类,所以这里有一个不同的尝试。

可观测收集(T)类有一个 移动方式,它可以完全满足您的需要。

public void Move(int oldIndex, int newIndex)

下面是这样实现的 差不多吧

T item = base[oldIndex];
base.RemoveItem(oldIndex);
base.InsertItem(newIndex, item);

因此,正如您所看到的,其他人建议的交换方法实际上就是 可观测收藏在它自己的 Move 方法中所做的。

UPDATE 2015-12-30: 现在你可以在 corefx 中看到 让开MoveItem方法的源代码,而不需要使用 Refector/ILSpy。NET 是开源的。

我创建了一个在列表中移动项的扩展方法。

如果我们要移动一个 存在项目,索引不应该移动,因为我们要将一个项目移动到列表中的 存在索引位置。

@ Oliver 在下面提到的边缘情况(将一个项目移动到列表的末尾)实际上会导致测试失败,但这是设计好的。要在列表末尾插入一个 新的项,我们只需调用 List<T>.Addlist.Move(predicate, list.Count) 应该失败,因为这个索引位置在移动之前不存在。

无论如何,我已经创建了两个额外的扩展方法,MoveToEndMoveToBeginning,它们的源代码可以在 给你中找到。

/// <summary>
/// Extension methods for <see cref="System.Collections.Generic.List{T}"/>
/// </summary>
public static class ListExtensions
{
/// <summary>
/// Moves the item matching the <paramref name="itemSelector"/> to the <paramref name="newIndex"/> in a list.
/// </summary>
public static void Move<T>(this List<T> list, Predicate<T> itemSelector, int newIndex)
{
Ensure.Argument.NotNull(list, "list");
Ensure.Argument.NotNull(itemSelector, "itemSelector");
Ensure.Argument.Is(newIndex >= 0, "New index must be greater than or equal to zero.");


var currentIndex = list.FindIndex(itemSelector);
Ensure.That<ArgumentException>(currentIndex >= 0, "No item was found that matches the specified selector.");


// Copy the current item
var item = list[currentIndex];


// Remove the item
list.RemoveAt(currentIndex);


// Finally add the item at the new index
list.Insert(newIndex, item);
}
}


[Subject(typeof(ListExtensions), "Move")]
public class List_Move
{
static List<int> list;


public class When_no_matching_item_is_found
{
static Exception exception;


Establish ctx = () => {
list = new List<int>();
};


Because of = ()
=> exception = Catch.Exception(() => list.Move(x => x == 10, 10));


It Should_throw_an_exception = ()
=> exception.ShouldBeOfType<ArgumentException>();
}


public class When_new_index_is_higher
{
Establish ctx = () => {
list = new List<int> { 1, 2, 3, 4, 5 };
};


Because of = ()
=> list.Move(x => x == 3, 4); // move 3 to end of list (index 4)


It Should_be_moved_to_the_specified_index = () =>
{
list[0].ShouldEqual(1);
list[1].ShouldEqual(2);
list[2].ShouldEqual(4);
list[3].ShouldEqual(5);
list[4].ShouldEqual(3);
};
}


public class When_new_index_is_lower
{
Establish ctx = () => {
list = new List<int> { 1, 2, 3, 4, 5 };
};


Because of = ()
=> list.Move(x => x == 4, 0); // move 4 to beginning of list (index 0)


It Should_be_moved_to_the_specified_index = () =>
{
list[0].ShouldEqual(4);
list[1].ShouldEqual(1);
list[2].ShouldEqual(2);
list[3].ShouldEqual(3);
list[4].ShouldEqual(5);
};
}
}

我知道这个问题已经很老了,但是我把 javascript 代码的 这个响应改编成了 C # ,希望能有所帮助

public static void Move<T>(this List<T> list, int oldIndex, int newIndex)
{
// exit if positions are equal or outside array
if ((oldIndex == newIndex) || (0 > oldIndex) || (oldIndex >= list.Count) || (0 > newIndex) ||
(newIndex >= list.Count)) return;
// local variables
var i = 0;
T tmp = list[oldIndex];
// move element down and shift other elements up
if (oldIndex < newIndex)
{
for (i = oldIndex; i < newIndex; i++)
{
list[i] = list[i + 1];
}
}
// move element up and shift other elements down
else
{
for (i = oldIndex; i > newIndex; i--)
{
list[i] = list[i - 1];
}
}
// put element from position 1 to destination
list[newIndex] = tmp;
}

这就是我如何实现 move 元素扩展方法的。它可以很好地处理元素的前后移动和极端移动。

public static void MoveElement<T>(this IList<T> list, int fromIndex, int toIndex)
{
if (!fromIndex.InRange(0, list.Count - 1))
{
throw new ArgumentException("From index is invalid");
}
if (!toIndex.InRange(0, list.Count - 1))
{
throw new ArgumentException("To index is invalid");
}


if (fromIndex == toIndex) return;


var element = list[fromIndex];


if (fromIndex > toIndex)
{
list.RemoveAt(fromIndex);
list.Insert(toIndex, element);
}
else
{
list.Insert(toIndex + 1, element);
list.RemoveAt(fromIndex);
}
}

更简单的家伙只是这样做

    public void MoveUp(object item,List Concepts){


int ind = Concepts.IndexOf(item.ToString());


if (ind != 0)
{
Concepts.RemoveAt(ind);
Concepts.Insert(ind-1,item.ToString());
obtenernombres();
NotifyPropertyChanged("Concepts");
}}

对 MoveDown 执行相同的操作,但是更改“ if (ind! = Concepts. Count ())”和 Concepts. Insert (ind + 1,item.ToString ())的 if;