Swift使用for-in循环替换数组中的字符串

时间:2016-03-04 17:41:49

标签: arrays string swift for-in-loop

作为一项学习练习,我尝试使用for-in循环替换String中的Array(使用字典值)如果StringDictionary中的现有密钥。我已经知道如何使用.stringByReplacingOccurrencesOfString执行此操作,但我想了解我在这里做错了什么,以及如何使用for-in循环来完成此操作。

let sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]
var toArray = sillyMonkeyString.componentsSeparatedByString(" ")
// desired result is "A  stole my "

以下是没有用的:

for var str in toArray {
    if let val = dictionary[str] {
        str = val                  
    }
}
let backToString = toArray.joinWithSeparator(" ")

工作原理:

var newArray = [String]()
for var str in toArray {
    if let val = dictionary[str] {
        str = val
    }
    newArray.append(str)
}
let backToString = newArray.joinWithSeparator(" ")

这是有效的,因为我正在创建一个新数组并附加到新数组。但是,我原来的数组 是可变的,那么为什么第一个解决方案没有在for-in循环内的原始str中正确地将val分配给Array?我发现的唯一其他相关问题here有一个很好的单行答案,并没有解释我是否可以使用for-in循环完成此操作。

更新:我不建议为此特定用例实现for-in循环。我问这个问题要学习如何来做到这一点。如果用户想用字典替换部分字符串,我强烈建议您考虑使用下面一种更有效的Swifty解决方案(这可能不是可接受的解决方案)

8 个答案:

答案 0 :(得分:2)

'纯'斯威夫特(没有进口基金会)和'功能性'方式导致

let sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

let arr = sillyMonkeyString.characters.split(" ").map(String.init)
let result = arr.map { dictionary[$0] ?? $0 }.joinWithSeparator(" ")

print(result)
// A  stole my 

如果需要 for in循环,则

var resArr:[String] = []
for txt in arr {
    resArr.append(dictionary[txt] ?? txt)
}
let result2 = resArr.joinWithSeparator(" ") // A  stole my "

如果您想要变异解决方案......

let sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

var arr = sillyMonkeyString.characters.split(" ").map(String.init)

for (idx,value) in arr.enumerate() {
    arr[idx] = dictionary[value] ?? value
}
let result3 = arr.joinWithSeparator(" ") // "A  stole my "

如果您不喜欢enumerate(),则可以使用索引

let sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

var arr = sillyMonkeyString.characters.split(" ").map(String.init)

for i in arr.indices {
    arr[i] = dictionary[arr[i]] ?? arr[i]
}
let result4 = arr.joinWithSeparator(" ") // "A  stole my "

答案 1 :(得分:1)

When declaring something as "var" in a for loop or "if var"(deprecated) statement, the value is copied to that variable, not the reference. So when you change "val", you're changing that local variable and not changing the object that exists in toArray

If you want to change it within the array, this should work (not compiled fyi):

for str in toArray {
    if let val = dictionary[str] {
        toArray[toArray.indexOf(str)] = val
    }
}

Alternately, you can track the index instead with

for i in 0 ..< toArray.count {
    if let val = dictionary[toArray[i]] {
        toArray[i] = val
    }
}

To give an comparable example to the link you sent, you could do something like this:

toArray = toArray.map { dictionary[$0] ?? $0 }

If you're unfamiliar with the map function, I would suggest looking it up as it's one of the best features in swift! :)

答案 2 :(得分:1)

str = val will only change the value in your local variable, which is valid only in the scope of the for loop. The value in the array will no be changed. What you want really is:

for i in 0..< toArray.count {
    if let val = dictionary[toArray[i]] {
        toArray[i] = val
    }
}

答案 3 :(得分:1)

This is the solution I came up with. I'll consider using others since many have recommended that using .indexOf is very expensive. Rather than assigning to an ivar, I'm assigning val directly to the item at the current index in the original array. I'm all for learning and implementing what is least costly. However, you got to admit this is clean and short. (though not the most efficient)

for var str in toArray {
    if let val = dictionary[str] {
        toArray[toArray.indexOf(str)!] = val
    }
}

答案 4 :(得分:1)

这种方法怎么样:

var sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]
var toArray = sillyMonkeyString.componentsSeparatedByString(" ")

for (index, string) in toArray.enumerate()
{
  if let val = dictionary[string]
  {
    toArray[index] = val
  }
}
let finalString = toArray.joinWithSeparator(" ")

该代码使用for ... in的变体返回数组中的对象,将索引作为元组返回。其他一些答案使用indexOfindexOf计算成本高,而且可能存在风险。数组可以包含同一对象的多个副本,因此有问题的字符串可能出现在多个位置。在这个特定的例子中,它的工作原理是因为我们从前到后循环遍历单词数组,在我们去的时候替换匹配的单词。因此,indexOf将始终找到第一个剩余的字符串。然而,在大型阵列上它仍然很慢。

答案 5 :(得分:1)

您可以使用forEach迭代字典键/值对并将其替换为:

var sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

dictionary.forEach{ sillyMonkeyString = sillyMonkeyString.stringByReplacingOccurrencesOfString($0.0, withString: $0.1) }
print(sillyMonkeyString)  // "A  stole my "

答案 6 :(得分:1)

关于&#34;出了什么问题&#34;在代码中没有工作:

mapOfPermissions.put(current,new HashSet<String>(setOfArray));

for循环中的str变量不是对toArray元素的引用,而是对它的副本的引用。因此,在循环中修改str对它来自的数组没有影响。

答案 7 :(得分:0)

As others have said, instead of

for var str in toArray {

if must be

for str in toArray {

But I want to show another approach, using enumerate() on dictionary

var sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

for (_ ,v) in dictionary.enumerate() {
    sillyMonkeyString = sillyMonkeyString.stringByReplacingOccurrencesOfString(v.0, withString: v.1)
}

print(sillyMonkeyString)

prints A stole my

enumerate() returns a tuple containing of the index and the tuple with the key and value.

and to make tanzolone happy, though this is a rather stupid approach:

let sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]
var toArray = sillyMonkeyString.componentsSeparatedByString(" ")

for (i,v) in dictionary.enumerate() {
    for (j,s) in toArray.enumerate() {
        if s == v.0 {
            toArray[j] = v.1
        }
    }
}

print(toArray.joinWithSeparator(" "))

enumeration with for in

var sillyMonkeyString = "A monkey stole my iPhone"
let dictionary = ["monkey": "", "iPhone":""]

for (k,v) in dictionary{
    sillyMonkeyString = sillyMonkeyString.stringByReplacingOccurrencesOfString(k, withString: v)
}

print(sillyMonkeyString)