Swift에서 배열의 항목을 새 위치로 다시 정렬하는 방법은 무엇입니까?
배열을 고려합니다.[1,2,3,4]배열 항목을 새 위치로 다시 정렬하려면 어떻게 해야 합니까?
예:
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].
Swift 3.0+:
let element = arr.remove(at: 3)
arr.insert(element, at: 2)
및 함수 형태:
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:
그러면 3이 4번 위치에 놓입니다.
let element = arr.removeAtIndex(3)
arr.insert(element, atIndex: 2)
일반적인 기능도 만들 수 있습니다.
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
}
그var arr입력 매개 변수를 지정하지 않고 변환할 수 없기 때문에 여기에 필요합니다.in-out하지만 우리의 경우 부작용이 없는 순수한 기능을 얻게 되는데, 제 생각에는 추론하기 훨씬 쉽습니다.그러면 다음과 같이 부를 수 있습니다.
let arr = [1,2,3,4]
rearrange(arr, fromIndex: 2, toIndex: 0) //[3,1,2,4]
모두 훌륭한 답변입니다!벤치마크 및 GIF 팬을 위한 성능과 보너스를 고려한 보다 완벽한 Swift 5 솔루션이 있습니다. ✌️
extension Array where Element: Equatable
{
mutating func move(_ element: Element, to newIndex: Index) {
if let oldIndex: Int = self.firstIndex(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)
}
}

편집/업데이트:스위프트 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]
레오의 좋은 조언.
스위프트 3의 경우...5.5:
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)
var arr = ["one", "two", "three", "four", "five"]
// Swap elements at index: 2 and 3
print(arr)
arr.swapAt(2, 3)
print(arr)
스위프트 5
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)
}
}
스왑 방법을 사용하여 어레이의 항목을 스왑할 수 있습니다.
var arr = ["one", "two", "three", "four", "five"]
// Swap elements at index: 2 and 3
print(arr)
swap(&arr[2], &arr[3])
print(arr)
@ian은 좋은 솔루션을 제공했지만 어레이가 경계를 벗어나면 충돌할 것입니다. 추가로 확인하십시오.
extension Array where Element: Equatable {
public mutating func move(_ element: Element, to newIndex: Index) {
if let oldIndex: Int = index(of: element) {
self.move(from: oldIndex, to: newIndex)
}
}
public mutating func moveToFirst(item: Element) {
self.move(item, to: 0)
}
public mutating func move(from oldIndex: Index, to newIndex: Index) {
// won't rebuild array and will be super efficient.
if oldIndex == newIndex { return }
// Index out of bound handle here
if newIndex >= self.count { return }
// Don't work for free and use swap when indices are next to each other - this
if abs(newIndex - oldIndex) == 1 { return self.swapAt(oldIndex, newIndex) }
// Remove at old index and insert at new location
self.insert(self.remove(at: oldIndex), at: newIndex)
}
}
배열의 경우 swift에 이동 기능이 없습니다.인덱스에서 개체를 제거하고 '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
Swift 4 - 항목 그룹을 이동하는 솔루션IndexSet인덱스를 그룹화하여 대상 인덱스로 이동합니다.에 대한 확장을 통해 실현됨RangeReplaceableCollection의 모든 항목을 제거하고 반환하는 방법을 포함합니다.IndexSet구성 기능을 유지하면서 정수보다 요소를 제한하는 것보다 확장을 더 일반화된 형태로 제한하는 방법을 잘 몰랐습니다.IndexSetsSwift Protocols에 대한 제 지식은 그렇게 광범위하지 않기 때문입니다.
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
}
}
다음은 어레이를 인플레이스로 변경하고 변경된 어레이를 반환하는 기능을 모두 갖춘 솔루션입니다.
extension Array {
func rearranged(from fromIndex: Int, to toIndex: Int) -> [Element] {
var arr = self
let element = arr.remove(at: fromIndex)
if toIndex >= self.count {
arr.append(element)
} else {
arr.insert(element, at: toIndex)
}
return arr
}
mutating func rearrange(from fromIndex: Int, to toIndex: Int) {
let element = self.remove(at: fromIndex)
if toIndex >= self.count {
self.append(element)
} else {
self.insert(element, at: toIndex)
}
}
}
macOS 10.15, iOS 14 이후로MutableCollection방법이 있습니다.move(fromOffsets:toOffset:).
https://developer.apple.com/documentation/swift/mutablecollection/move(fromoffsets:tooffset:)
Swift 4로 업데이트, 배열 인덱스 스와이프
for (index,addres) in self.address.enumerated() {
if addres.defaultShipping == true{
let defaultShipping = self.address.remove(at: index)
self.address.insert(defaultShipping, at: 0)
}
}
효율적인 솔루션:
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
}
}
func adjustIndex(_ index: Int, forRemovalAt removed: Int) -> Int {
return index <= removed ? index : index - 1
}
extension Array
{
mutating func move(from oldIndex: Index, to newIndex: Index) {
insert(remove(at: oldIndex), at: adjustIndex(newIndex, forRemovalAt: oldIndex))
}
}
Swift 5 테스트 완료
케이크에 토핑을 추가하기 위해, 저는 처리할 기능을 추가했습니다.Array<Dictionary<String,Any>>
제 답변의 주요 출처는 여기 https://stackoverflow.com/a/50205000/4131763, 입니다.
여기 제 버전이 있습니다.
//Array+Extension.swift,
extension Array where Element: Equatable
{
mutating func move(_ element: Element, to newIndex: Index) {
if let oldIndex: Int = self.firstIndex(of: element) { self.move(from: oldIndex, to: newIndex) }
}
}
extension Array where Element == Dictionary<String, Any> {
mutating func move(_ element:Element, to newIndex: Index) {
if let oldIndex = self.firstIndex(where: { ($0.keys.first ?? "") == (element.keys.first ?? "") }) {
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)
}
}
사용 방법,
if let oldIndex = array.firstIndex(where: { ($0["ValidationTitle"] as! String) == "MEDICALNOTICEREQUIRED" }) {
let obj = array[oldIndex]
array.move(obj, to: array.startIndex)
}
if let oldIndex = array.firstIndex(where: { ($0["ValidationTitle"] as! String) == "HIGHRISKCONFIRMATION" }) {
let obj = array[oldIndex]
let oldIndexMEDICALNOTICEREQUIRED = array.firstIndex(where: { ($0["ValidationTitle"] as! String) == "MEDICALNOTICEREQUIRED" })!
array.move(obj, to: oldIndexMEDICALNOTICEREQUIRED + 1)
}
if let oldIndex = array.firstIndex(where: { ($0["ValidationTitle"] as! String) == "UNLICENCEDCONFIRMATION" }) {
let obj = array[oldIndex]
let oldIndexHIGHRISKCONFIRMATION = array.firstIndex(where: { ($0["ValidationTitle"] as! String) == "HIGHRISKCONFIRMATION" })!
array.move(obj, to: oldIndexHIGHRISKCONFIRMATION + 1)
}
Leo Dabus의 솔루션은 훌륭하지만 전제 조건(!=에서 &&index.dll(!=에서 &&index.dll(to))을 사용하면 조건이 충족되지 않을 경우 앱이 충돌합니다.가드와 if문으로 변경했는데, 어떤 이유로 조건이 충족되지 않으면 아무 일도 일어나지 않고 앱이 계속 진행됩니다.앱이 손상될 수 있는 확장은 피해야 한다고 생각합니다.재배열 기능을 만들려면 Bool을 반환합니다. 성공하면 true이고 실패하면 false입니다.보다 안전한 솔루션:
extension Array {
mutating func rearrange(from: Int, to: Int) {
guard from != to else { return }
//precondition(from != to && indices.contains(from) && indices.contains(to), "invalid indexes")
if indices.contains(from) && indices.contains(to) {
insert(remove(at: from), at: to)
}
}
기능(빠르지는 않지만 보편적인..조회/제거/삽입):
func c_move_to(var array:Array,var from:Int,var to:Int):
var val = array[from]
array.remove(from)
array.insert(to,val)
return array
사용 방법:
print("MOVE 0 to 3 [1,2,3,4,5]" , c_move_to([1,2,3,4,5],0,3))
print("MOVE 1 to 2 [1,2,3,4,5]" , c_move_to([1,2,3,4,5],1,2))
뱉기:
MOVE 0 to 3 [1,2,3,4,5][2, 3, 4, 1, 5]
MOVE 1 to 2 [1,2,3,4,5][1, 3, 2, 4, 5]
이 해결책은 어떻습니까?변경할 요소와 변경할 요소가 변경되었습니다.
// Extenstion
extension Array where Element: Equatable {
mutating func change(_ element: Element, to newIndex: Index) {
if let firstIndex = self.firstIndex(of: element) {
self.insert(element, at: 0)
self.remove(at: firstIndex + 1)
}
}
}
// Example
var testArray = ["a", "b", "c", "EE", "d"]
testArray.change("EE", to: 0)
// --> Result
// ["EE", "a", "b", "c", "d"]
언급URL : https://stackoverflow.com/questions/36541764/how-to-rearrange-item-of-an-array-to-new-position-in-swift
'programing' 카테고리의 다른 글
| 표 성능 대보기 (0) | 2023.08.31 |
|---|---|
| Laravel 4에서 원시 SQL 쿼리 이스케이프 (0) | 2023.08.31 |
| 날짜 데이터 유형 기본값을 설정하는 방법은 무엇입니까? (0) | 2023.08.31 |
| JavaScript 개체의 속성을 계산하려면 어떻게 해야 합니까? (0) | 2023.08.31 |
| Javascript Array Concat이 작동하지 않습니다. 왜죠? (0) | 2023.08.31 |