programing

일반 목록 - 목록 내 항목 이동

sourcejob 2023. 4. 24. 23:08
반응형

일반 목록 - 목록 내 항목 이동

총칭 리스트가 있는데oldIndex및 anewIndex가치.

아이템을 이동시키고 싶다.oldIndex,로.newIndex...가능한 한 단순하게.

좋은 의견이라도 있나?

메모

아이템은 다음 위치에 있는 아이템 사이에 있어야 합니다.(newIndex - 1)그리고.newIndex 제거되기 전에요

"일반 목록"이라고 말씀하셨지만 List(T) 클래스를 사용할 필요가 있다고 명시하지 않았으므로 다른 방법을 제시하겠습니다.

ObservableCollection(T) 클래스에는 원하는 대로 정확히 수행하는 이동 메서드가 있습니다.

public void Move(int oldIndex, int newIndex)

그 아래는 기본적으로 이렇게 구현되어 있습니다.

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

따라서 다른 사용자가 제안한 스왑 방법은 기본적으로 Observable Collection이 자체 Move 메서드에서 수행하는 작업입니다.

UPDATE 2015-12-30 : Reflector/를 사용하지 않고 corefx에서 Move 및 MoveItem 메서드의 소스 코드를 직접 확인하실 수 있습니다.이후 ILSpy.NET은 오픈소스입니다

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);
            }
        }

    }

오래된 질문인 건 알지만 자바스크립트 코드의 이 응답을 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;
}

목록 <T>() 및 목록 < 목록 <T>제거되지 않은 항목을 제거하지 마십시오.

따라서 이 사용하셔야 합니다.

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

목록에서 항목을 이동할 수 있도록 확장 방법을 만들었습니다.

목록에서 기존 인덱스를 기존 인덱스 위치로 이동하면 인덱스를 이동할 수 없습니다.

@Oliver가 다음에 나타내는 엣지 케이스(목록의 끝으로 항목을 이동)는 실제로 테스트에 실패하지만, 이는 의도된 것입니다.목록 끝에 새 항목을 삽입하려면 전화만 하면 됩니다.List<T>.Add.list.Move(predicate, list.Count) 인덱스 위치가 이동 전에 존재하지 않기 때문에 실패합니다.

어쨌든 두 가지 추가 확장 방법을 만들었습니다.MoveToEnd그리고.MoveToBeginning, 그 출처는 이쪽입니다.

/// <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);
        };
    }
}

현재 항목 삽입 위치oldIndex에 있다newIndex그런 다음 원래 인스턴스를 제거합니다.

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

삽입으로 인해 제거할 항목의 색인이 변경될 수 있음을 고려해야 합니다.

다음 중 하나를 예상합니다.

// 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가 없습니다.

가장 간단한 방법:

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

편집

그 질문은 명확하지 않다...우리는 어디에 있든 상관하지 않기 때문에list[newIndex]에 관계없이 item goes는 다음과 같습니다.

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

이 솔루션은 목록 삽입/삭제를 수반하지 않기 때문에 가장 빠릅니다.

이렇게 해서 move element extension 메서드를 구현했습니다.요소의 전후 및 극한까지 이동하는 것을 매우 잘 처리합니다.

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를 if(ind!=외출.Count()" 및 Concepts.insert(ind+1, item).ToString();

언급URL : https://stackoverflow.com/questions/450233/generic-list-moving-an-item-within-the-list

반응형