This question already has answers here:
How to remove an element from an array in Swift
(18 answers)
Closed 4 years ago.
I have a [[String]] like
myArr = [["1_2","1_3","1_4"], ["2_1","2_2","2_3"], ["3_1","3_2","3_3"]] then
I Want to remove element like this
bypassArr = ["1_2","2_3","3_2"]
how to remove bypassArr from myArr using element. or how can i get this type of result.
result = [["1_3","1_4"], ["2_1","2_2"], ["3_1","3_3"]]
If the intention is to remove all elements from bypassArr in the “inner” arrays from myArr then a combination of map() and filter() does the trick:
let myArr = [["1_2","1_3","1_4"], ["2_1","2_2","2_3"], ["3_1","3_2","3_3"]]
let bypassArr = ["1_2","2_3","3_2"]
let result = myArr.map { innerArray in
innerArray.filter { elem in
!bypassArr.contains(elem)
}
}
print(result)
// [["1_3", "1_4"], ["2_1", "2_2"], ["3_1", "3_3"]]
The inner arrays are filtered to remove the given elements, and the outer array is mapped to the filtered results.
Or with short-hand parameter notation:
let result = myArr.map { $0.filter { !bypassArr.contains($0) }}
var myArr = [["1_2","1_3","1_4"], ["2_1","2_2","2_3"], ["3_1","3_2","3_3"]]
let bypassArr = ["1_2","2_3","3_2"]
if myArr.count == bypassArr.count {
myArr = bypassArr.enumerated().map({ (index, str) -> [String] in
if let strPos = myArr[index].firstIndex(of: str) {
myArr[index].remove(at: strPos)
}
return myArr[index]
})
}
print(myArr)
Related
I have an array:
let arr = ["Ivan Ivanov", "Bogdan Bogdanov", "Georgi Milchev", "Bogdan Petkov", "Vladimir Zahariev"]
let name = "Bogdan"
Search if array contains(name) and append the result to the new array without loop.
So new array have to be ["Bogdan Bogdanov", "Bogdan Petkov"]
Trying with: if arr.contains(where: {$0 == name}) { newArray.append($0) }
but it's not working. Error: Anonymous closure argument not contained in a closure
You need
let res = arr.compactMap { $0.contains(name) ? $0.components(separatedBy: " ").last! : nil }
This question already has answers here:
Error: Immutable value passed on reduce function
(3 answers)
Closed 7 years ago.
I'm using Xcode 6.4
I have an array of UIViews and I want to convert to a Dictionary with keys "v0", "v1".... Like so:
var dict = [String:UIView]()
for (index, view) in enumerate(views) {
dict["v\(index)"] = view
}
dict //=> ["v0": <view0>, "v1": <view1> ...]
This works, but I'm trying to do this in a more functional style. I guess it bothers me that I have to create the dict variable. I would love to use enumerate() and reduce() like so:
reduce(enumerate(views), [String:UIView]()) { dict, enumeration in
dict["v\(enumeration.index)"] = enumeration.element // <- error here
return dict
}
This feels nicer, but I'm getting the error: Cannot assign a value of type 'UIView' to a value of type 'UIView?' I have tried this with objects other an UIView (ie: [String] -> [String:String]) and I get the same error.
Any suggestions for cleaning this up?
try like this:
reduce(enumerate(a), [String:UIView]()) { (var dict, enumeration) in
dict["\(enumeration.index)"] = enumeration.element
return dict
}
Xcode 8 • Swift 2.3
extension Array where Element: AnyObject {
var indexedDictionary: [String:Element] {
var result: [String:Element] = [:]
for (index, element) in enumerate() {
result[String(index)] = element
}
return result
}
}
Xcode 8 • Swift 3.0
extension Array {
var indexedDictionary: [String: Element] {
var result: [String: Element] = [:]
enumerated().forEach({ result[String($0.offset)] = $0.element })
return result
}
}
Xcode 9 - 10 • Swift 4.0 - 4.2
Using Swift 4 reduce(into:) method:
extension Collection {
var indexedDictionary: [String: Element] {
return enumerated().reduce(into: [:]) { $0[String($1.offset)] = $1.element }
}
}
Using Swift 4 Dictionary(uniqueKeysWithValues:) initializer and passing a new array from the enumerated collection:
extension Collection {
var indexedDictionary: [String: Element] {
return Dictionary(uniqueKeysWithValues: enumerated().map{(String($0),$1)})
}
}
This question already has answers here:
Set operations (union, intersection) on Swift array?
(5 answers)
Closed 5 years ago.
How can I remove values array based on array other.
Example :-
Type ( Int )
var arrayOne = [1,2,3,4,5,6,7,8]
var arrayTwo = [1,2,4,5,6,7]
I want the next result :-
result = [3,8]
User Set for simple result
var arrayOne = [1,2,3,4,5,6,7,8]
var arrayTwo = [1,2,4,5,6,7]
let set1:Set<Int> = Set(arrayOne)
let set2:Set<Int> = Set(arrayTwo)
let set3 = set1.symmetricDifference(set2)
Output :
{3, 8}
You can do it by converting them to Sets.
var arrayOne = [1,2,3,4,5,6,7,8]
var arrayTwo = [1,2,4,5,6,7]
let set1:Set<String> = Set(arrayOne)
let set2:Set<String> = Set(arrayTwo)
Use ExclusiveOr to do this.
//Swift 2.0
set1.exclusiveOr(array2) // result = {3,8}
//Swift 3.0
set1.symmetricDifference(set2) // result = {3,8}
This link might useful for you: Set operations (union, intersection) on Swift array?
also possible Duplicate as #user3589771 said.
You can do with below options.
// Option 1 - Using Set's
let arrayOne : Set = [1,2,3,4,5,6,7,8]
let arrayTwo : Set = [1,2,4,5,6,7]
var result = arrayOne.symmetricDifference(arrayTwo)
print(result) // {3,8}
// Option 2 - Using Array
var result1 = [Int]()
for value in arrayOne
{
if !arrayTwo.contains(value)
{
result1.append(value)
}
}
print(result1) // {3,8}
Use following working code -
let arrayOne = [1,2,3,4,5,6,7,8]
let arrayTwo = [1,2,4,5,6,7]
var result = [Int]()
for value in arrayOne
{
if !arrayTwo.contains(value)
{
result.append(value)
}
}
For example, I have an array like var myArray = ['player_static.png', 'player_run0.png', 'player_run1.png', 'player_run2.png', 'player_jump0.png', 'player_jump1.png']
Is there any simple way to get only the "player_runX.png" images?
You can use filter to get all elements that hasPrefix("player_run"):
let myArray = ["player_static.png", "player_run0.png", "player_run1.png", "player_run2.png", "player_jump0.png", "player_jump1.png"]
let playerRuns = myArray.filter{$0.hasPrefix("player_run")}
print(playerRuns) //["player_run0.png", "player_run1.png", "player_run2.png"]
One way to do this would be to iterate over the array and retrieve the elements that match the pattern. A very quick sample would be something like this:
var myArray = ["player_static.png", "player_run0.png", "player_run1.png", "player_run2.png", "player_jump0.png", "player_jump1.png"]
func getSubArray(array:[String],prefix:String) -> [String]
{
var newArray = [String]()
for img in array
{
if img.substringToIndex(img.startIndex.advancedBy(prefix.characters.count)) == prefix
{
newArray.append(img)
}
}
return newArray
}
var test = getSubArray(myArray, prefix: "player_run")
What woudl be a simple way to reduce a string like AAA:111;BBB:222;333;444;CCC:555 to a dictionary in Swift. I have the following code:
var str = "AAA:111;BBB:222;333;444;CCC:555"
var astr = str.componentsSeparatedByString(";").map { (element) -> [String:String] in
var elements = element.componentsSeparatedByString(":")
if elements.count < 2 {
elements.insert("N/A", atIndex: 0)
}
return [elements[0]:elements[1]]
}
The code above produces an Array of Dictionaries:
[["A": "111"], ["BBB": "222"], ["UKW": "333"], ["UKW": "444"], ["CCC": "555"]]
I want it to produce
["A": "111", "BBB": "222", "UKW": "333", "UKW": "444", "CCC": "555"]
but no mater what I try, since i call the map function on an Array it seems impossible to convert the nature of the map function's result.
NOTE: The dictionary in string format is described as either having KEY:VALUE; format or VALUE; format, in which case the mapping function will add the "N/A" as being the key of the unnamed value.
Any help on this matter is greatly appreciated.
Your map produces an array of dictionaries. When you want to combine them into 1, that's a perfect job for reduce:
func + <K,V>(lhs: Dictionary<K,V>, rhs: Dictionary<K,V>) -> Dictionary<K,V> {
var result = Dictionary<K,V>()
for (key, value) in lhs {
result[key] = value
}
for (key, value) in rhs {
result[key] = value
}
return result
}
var str = "AAA:111;BBB:222;333;444;CCC:555"
var astr = str
.componentsSeparatedByString(";")
.reduce([String: String]()) {
aggregate, element in
var elements = element.componentsSeparatedByString(":")
if elements.count < 2 {
elements.insert("N/A", atIndex: 0)
}
return aggregate + [elements[0]:elements[1]]
}
print(astr)
Swift has no default operator to "combine" two Dictionaries so you have to define one. Note that the + here is not commutative: dictA + dictB != dictB + dictA. If a key exist in both dictionaries, the value from the second dictionary will be used.
This is a work for reduce:
let str = "AAA:111;BBB:222;333;444;CCC:555"
let keyValueStrings = str.componentsSeparatedByString(";")
let dictionary = keyValueStrings.reduce([String: String]()) {
aggregate, element in
var newAggregate = aggregate
let elements = element.componentsSeparatedByString(":")
let key = elements[0]
// replace nil with the value you want to use if there is no value
let value = (elements.count > 1) ? elements[1] : nil
newAggregate[key] = value
return newAggregate
}
print(dictionary)
You can also make aggregate mutable directly:
let dictionary = keyValueStrings.reduce([String: String]()) {
(var aggregate: [String: String], element: String) -> [String: String] in
let elements = element.componentsSeparatedByString(":")
let key = elements[0]
// replace nil with the value you want to use if there is no value
let value = (elements.count > 1) ? elements[1] : nil
aggregate[key] = value
return aggregate
}
This is a functional approach, but you can achieve the same using a for iteration.
The reason this is happening is because map can only return arrays. If you are using this method to parse your string, then you need to convert it to a dictionary after.
var newDict = [String:String]()
for x in astr {
for (i, j) in x {
newDict[i] = j
}
}
The current issue with your code is that map function iterates over array containing [["key:value"],["key:value"]..] and you separate it again. But it returns ["key":"value"] which you then add to your array.
Instead you can add elements[0]:elements[1] directly to a locally kept variable which will fix your problem. Something like
finalVariable[elements[0]] = elements[1]