Arrays 如何在Swift中迭代移动数组中的项目
假设我们有一个数组:Arrays 如何在Swift中迭代移动数组中的项目,arrays,swift,sorting,Arrays,Swift,Sorting,假设我们有一个数组: var-sphabet=[“B”、“C”、“D”、“E”、“H”、“F”、“G”、“A”] 我们希望通过移动两个项对其进行排序:第7项(“A”)到位置0,第4项(“H”)到位置7,用元组数组描述: var移动=[(7,0)、(4,7)] 因此,期望的结果是: [“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”] 这很容易用以下方法解决: var scrambledAlphabet = ["B", "C", "D", "E", "H", "F", "G", "A
var-sphabet=[“B”、“C”、“D”、“E”、“H”、“F”、“G”、“A”]
我们希望通过移动两个项对其进行排序:第7项(“A”)到位置0,第4项(“H”)到位置7,用元组数组描述:
var移动=[(7,0)、(4,7)]
因此,期望的结果是:
[“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”]
这很容易用以下方法解决:
var scrambledAlphabet = ["B", "C", "D", "E", "H", "F", "G", "A"]
var moves = [(7, 0), (4, 7)]
for (i, j) in moves {
scrambledAlphabet.insert(scrambledAlphabet.remove(at: i), at: j)
}
print(scrambledAlphabet)
但它不起作用。输出为:
[“A”、“B”、“C”、“D”、“H”、“F”、“G”、“E”]
问题是,一旦第一个项目被移动,下一个项目的索引就会改变。那么,解决这个问题的最佳方法是什么?我发现这很难破解。感谢您的帮助
限制是两个变量,scrambledAlphabet
和moves
,必须能够增长到任意数量
还有一个重要的注意事项,移动到索引(元组中的第二个数字)指的是旧数组,不是新创建的数组。因此,输入[“B”、“C”、“E”、“D”、“H”、“F”、“G”、“A”]
和[(7,0)、(4,7)、(3,2)]
应导致:
[“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”]
很抱歉最后一点让人困惑。我想到了这个(我觉得有点笨拙)解决方案:
var newArray = Array(repeating: "", count: scrambledLetters.count)
for (start, end) in moves {
newArray[end] = scrambledLetters[start]
scrambledLetters[start] = ""
}
var scrambledLetterIndex = -1
func setScrambledLetterIndexToNextNonEmptyString() {
scrambledLetterIndex += 1
while scrambledLetterIndex < scrambledLetters.count - 1 && scrambledLetters[scrambledLetterIndex].isEmpty {
scrambledLetterIndex += 1
}
}
for i in newArray.indices {
if newArray[i] == "" {
setScrambledLetterIndexToNextNonEmptyString()
newArray[i] = scrambledLetters[scrambledLetterIndex]
}
}
scrambledLetters = newArray
然后,我慢慢地将加扰字母数组中的每个非空项复制到新数组的空位置
因为此解决方案使用空字符串,所以如果输入域包含空字符串,它将不起作用。如果是这种情况,您必须使用类似于
[String?]
的东西 一种可能的方法是使用所有索引的数组,这些索引不是任何移动的来源。然后,我们可以从一个移动或一个“其他索引”顺序填充目标:
func scramble<T>(array: [T], moves: [(Int, Int)]) -> [T] {
// Moves sorted by increasing destination index:
var moves = moves.sorted(by: { $0.1 < $1.1 })
// All indices which are not the source of a move:
let sourceIndices = Set(moves.map { $0.0 })
var otherIndices = array.indices.filter { !sourceIndices.contains($0)}
// Fill each position with an element of a move source,
// or one of the "other" array elements:
return array.indices.map {
if let (from, to) = moves.first, $0 == to {
moves.removeFirst()
return array[from]
} else {
return array[otherIndices.removeFirst()]
}
}
}
例2:
print(scramble(array: [0, 1, 2, 3, 4, 5, 6, 7],
moves: [(1, 6), (7, 2), (3, 5), (5, 3), (4, 7)]))
// [0, 2, 7, 5, 6, 3, 1, 4]
我通过将数组中的项目与其原始索引进行耦合来解决这个问题,并对移动进行排序,以便插入不会扰乱顺序。还将所有代码移动到数组扩展中:
extension Array where Element : Equatable {
mutating func moveItem(from fromIndex: Int, to toIndex: Int) {
self.insert(self.remove(at: fromIndex), at: toIndex)
}
func performIteratedMoves(_ moves: [(Int, Int)]) -> [Element] {
var array = self
let enumeratedArray = array.enumerated().map{ (index: $0, item: $1) }
let sortedMoves = moves.sorted { $0.1 > $1.1 }
for (i, j) in sortedMoves {
guard let (_, item) = enumeratedArray.first(where:{ $0.index == i }), let correctIndex = array.firstIndex(where:{ $0 == item }) else { continue }
array.moveItem(from: correctIndex, to: j)
}
return array
}
}
用法:
var scrambledAlphabet = ["B", "C", "E", "D", "H", "F", "G", "A"]
var moves = [(7, 0), (4, 7), (3, 2)]
print(scrambledAlphabet.performIteratedMoves(moves))
// ["A", "B", "C", "D", "E", "F", "G", "H"]
你能展示更多的输入和输出示例吗?我想检查我的解决方案是否正确。这将不起作用,因为一旦将索引7处的对象移动到索引0,索引4处的对象将不再是H,而是E,H的索引将是5@SandeepBhandari你已经指出了问题所在,那么解决方案是什么?@Sweeper输入是变量,请随意将其扩展到完整的字母表,并执行50个预定义的移动,以查看您的解决方案是否有效。
moveItem()
来自何处?啊,对不起。把它移到一个分机里。更新了帖子。用我的第二个例子试试这个,或者更简单地用[“A”、“B”、“C”、“D”]
和移动=[(2,1)、(3,0)]
。结果应该是[“D”、“C”、“A”、“B”]
,但是[“D”、“A”、“C”、“B”]
我曾多次尝试通过“更正索引”来解决您的问题,但都失败了。[“D”,“A”,“C”,“B”]
是正确的答案,“C”首先移动到“B”的位置,然后“D”移动到第一位置。请注意,这要求所有元素都是不同的:尝试[“A”,“B”,“A”,“C”]
使用移动=[(2,3)]
但是通过数组[“B”,“C”,“E”,“D”,“H”,“F”,“G”,“A”]
和移动[(7,0),(4,7),(3,2)]
这将返回[“A”,“B”,“D”,“C”,“E”,“F”,“G”,“H”]@turingtested:是的,它返回了,而且在我看来是正确的。也许我误解了任务?您希望得到什么结果?Expexted:[“A”、“B”、“C”、“D”、“E”、“F”、“G”、“H”],因为字母3(“D”)应该移动到位置2。@turingtested:对不起,我不明白。在您的预期结果中,字母“D”仍然位于第3位(指数以零为基础)。如果将“D”移动到位置2,则新数组以[“A”、“B”、“D”、…]开始@turingtested:移动[(7,0)、(4,7)、(3,3)]
将得到预期结果(D在位置3“固定”)。
extension Array where Element : Equatable {
mutating func moveItem(from fromIndex: Int, to toIndex: Int) {
self.insert(self.remove(at: fromIndex), at: toIndex)
}
func performIteratedMoves(_ moves: [(Int, Int)]) -> [Element] {
var array = self
let enumeratedArray = array.enumerated().map{ (index: $0, item: $1) }
let sortedMoves = moves.sorted { $0.1 > $1.1 }
for (i, j) in sortedMoves {
guard let (_, item) = enumeratedArray.first(where:{ $0.index == i }), let correctIndex = array.firstIndex(where:{ $0 == item }) else { continue }
array.moveItem(from: correctIndex, to: j)
}
return array
}
}
var scrambledAlphabet = ["B", "C", "E", "D", "H", "F", "G", "A"]
var moves = [(7, 0), (4, 7), (3, 2)]
print(scrambledAlphabet.performIteratedMoves(moves))
// ["A", "B", "C", "D", "E", "F", "G", "H"]