web-dev-qa-db-fra.com

Comment réorganiser un élément d'un tableau à une nouvelle position dans Swift?

Considérons le tableau [1,2,3,4]. Comment puis-je réorganiser l'élément de tableau à la nouvelle position.

Par exemple:

put 3 into position 4 [1,2,4,3]

put 4 in to position 1 [4,1,2,3]

put 2 into position 3 [1,3,2,4].

51
Morty Choi

Swift 3.0+:

let element = arr.remove(at: 3)
arr.insert(element, at: 2)

et sous forme de fonction:

func rearrange<T>(array: Array<T>, fromIndex: Int, toIndex: Int) -> Array<T>{
    var arr = array
    let element = arr.remove(at: fromIndex)
    arr.insert(element, at: toIndex)

    return arr
}

Swift 2.0:

Cela met 3 en position 4.

let element = arr.removeAtIndex(3)
arr.insert(element, atIndex: 2)

Vous pouvez même créer une fonction générale:

func rearrange<T>(array: Array<T>, fromIndex: Int, toIndex: Int) -> Array<T>{
    var arr = array
    let element = arr.removeAtIndex(fromIndex)
    arr.insert(element, atIndex: toIndex)

    return arr
}

La vararr est nécessaire ici, car vous ne pouvez pas muter le paramètre d'entrée sans le spécifier comme étant in-out. Dans notre cas, cependant, nous obtenons des fonctions pures sans effets secondaires, ce qui est beaucoup plus facile à raisonner, à mon avis. Vous pourriez alors l'appeler comme ceci:

let arr = [1,2,3,4]
rearrange(arr, fromIndex: 2, toIndex: 0) //[3,1,2,4]
95
Luka Jacobowitz

modifier/mettre à jour: Swift 3.x

extension RangeReplaceableCollection where Indices: Equatable {
    mutating func rearrange(from: Index, to: Index) {
        precondition(from != to && indices.contains(from) && indices.contains(to), "invalid indices")
        insert(remove(at: from), at: to)
    }
}

var numbers = [1,2,3,4]
numbers.rearrange(from: 1, to: 2)

print(numbers)  // [1, 3, 2, 4]
36
Leo Dabus

Toutes les bonnes réponses! Voici une solution Swift 4 plus complète, axée sur la performance et les bonus pour les fans de benchmark et GIF. ✌️

extension Array where Element: Equatable
{
    mutating func move(_ element: Element, to newIndex: Index) {
        if let oldIndex: Int = self.index(of: element) { self.move(from: oldIndex, to: newIndex) }
    }
}

extension Array
{
    mutating func move(from oldIndex: Index, to newIndex: Index) {
        // Don't work for free and use swap when indices are next to each other - this
        // won't rebuild array and will be super efficient.
        if oldIndex == newIndex { return }
        if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }
        self.insert(self.remove(at: oldIndex), at: newIndex)
    }
}

GIF

21
Ian Bytchek

Bon conseil de Leo.

pour Swift 3:

extension Array {  
    mutating func rearrange(from: Int, to: Int) {
        insert(remove(at: from), at: to)
    }
}

var myArray = [1,2,3,4]
myArray.rearrange(from: 1, to: 2)   
print(myArray)
19
ingconti
var arr = ["one", "two", "three", "four", "five"]

// Swap elements at index: 2 and 3
print(arr)
arr.swapAt(2, 3)
print(arr)
8
Vinoth Anandan

Swift 4.2

extension Array where Element: Equatable {
    mutating func move(_ item: Element, to newIndex: Index) {
        if let index = index(of: item) {
            move(at: index, to: newIndex)
        }
    }

    mutating func bringToFront(item: Element) {
        move(item, to: 0)
    }

    mutating func sendToBack(item: Element) {
        move(item, to: endIndex-1)
    }
}

extension Array {
    mutating func move(at index: Index, to newIndex: Index) {
        insert(remove(at: index), at: newIndex)
    }
}
6
Zelko

Nous pouvons utiliser la méthode swap pour échanger des éléments dans un tableau:

var arr = ["one", "two", "three", "four", "five"]

// Swap elements at index: 2 and 3
print(arr)
swap(&arr[2], &arr[3])
print(arr)
5
Muhammad Yawar Ali

Solution efficace:

extension Array 
{
    mutating func move(from sourceIndex: Int, to destinationIndex: Int)
    {
        guard
            sourceIndex != destinationIndex
            && Swift.min(sourceIndex, destinationIndex) >= 0
            && Swift.max(sourceIndex, destinationIndex) < count
        else {
            return
        }

        let direction = sourceIndex < destinationIndex ? 1 : -1
        var sourceIndex = sourceIndex

        repeat {
            let nextSourceIndex = sourceIndex + direction
            swapAt(sourceIndex, nextSourceIndex)
            sourceIndex = nextSourceIndex
        }
        while sourceIndex != destinationIndex
    }
}
1
Enlod

Swift 4 - Solution permettant de déplacer un groupe d'éléments d'un IndexSet index, de les regrouper et de les déplacer vers un index de destination. Réalisé via une extension à RangeReplaceableCollection. Inclut une méthode pour supprimer et retourner tous les éléments dans un IndexSet. Je ne savais pas comment contraindre l'extension à une forme plus générale que celle de l'élément tout en conservant la possibilité de construire IndexSets car ma connaissance de Swift Protocoles est pas si vaste.

extension RangeReplaceableCollection where Self.Indices.Element == Int {

    /**
        Removes the items contained in an `IndexSet` from the collection.
        Items outside of the collection range will be ignored.

        - Parameter indexSet: The set of indices to be removed.
        - Returns: Returns the removed items as an `Array<Self.Element>`.
    */
    @discardableResult
    mutating func removeItems(in indexSet: IndexSet) -> [Self.Element] {

        var returnItems = [Self.Element]()

        for (index, _) in self.enumerated().reversed() {
            if indexSet.contains(index) {
                returnItems.insert(self.remove(at: index), at: startIndex)
            }
        }
        return returnItems
    }


    /**
        Moves a set of items with indices contained in an `IndexSet` to a     
        destination index within the collection.

        - Parameters:
            - indexSet: The `IndexSet` of items to move.
            - destinationIndex: The destination index to which to move the items.
        - Returns: `true` if the operation completes successfully else `false`.

        If any items fall outside of the range of the collection this function 
        will fail with a fatal error.
    */
    @discardableResult
    mutating func moveItems(from indexSet: IndexSet, to destinationIndex: Index) -> Bool {

        guard indexSet.isSubset(of: IndexSet(indices)) else {
            debugPrint("Source indices out of range.")
            return false
            }
        guard (0..<self.count + indexSet.count).contains(destinationIndex) else {
            debugPrint("Destination index out of range.")
            return false
        }

        let itemsToMove = self.removeItems(in: indexSet)

        let modifiedDestinationIndex:Int = {
            return destinationIndex - indexSet.filter { destinationIndex > $0 }.count
        }()

        self.insert(contentsOf: itemsToMove, at: modifiedDestinationIndex)

        return true
    }
}
1
CodeCoordination

Il n'y a pas de fonctionnalité de déplacement dans Swift pour les tableaux. Vous pouvez prendre un objet à un index en le supprimant et le placer dans votre index favori à l'aide de 'insert'

var swiftarray = [1,2,3,4]
let myobject = swiftarray.removeAtIndex(1) // 2 is the object at 1st index
let myindex = 3
swiftarray.insert(myobject, atIndex: myindex) // if you want to insert the    object to a particular index here it is 3
swiftarray.append(myobject) // if you want to move the object to last index
1
user4615157

Mise à jour avec Swift 4, index de tableau de balayage

for (index,addres) in self.address.enumerated() {
     if addres.defaultShipping == true{
          let defaultShipping = self.address.remove(at: index)
          self.address.insert(defaultShipping, at: 0)
     }
}
0
Raj Joshi