Swift: Get multiple array values like "x" - arrays

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")

Related

how can I combine 2 array to create array of arrays in swift

I have latsArr and LongsArr filled from firebase automatically.
I want to populate latsAndLongsArray in viewDidLoad function. How can I do that?
var latsArr = [1111.0,2222.0,333.0]
var longsArr = [444.0,555.0,666.0]
var latsAndLongs = [[111.0,444.0],[222.0,555.0],[333.0,666.0]]
Use the zip(_:_:) and map(_:) methods combined to get the expected result:
let latsAndLongs = zip(latsArr, longsArr).map { [$0.0, $0.1] }
var latsAndLongs = zip(latsArr, longsArr).map({[$0.0, $0.1]})
One option (which uses tuples instead of arrays) is to use zip.
var latsArr = [1111.0,2222.0,333.0]
var longsArr = [444.0,555.0,666.0]
var latsAndLongs = zip(latsArr, longsArr)
// latsAndLongs == [(1111.0, 444.0), (2222.0, 555.0), (333.0, 666.0)]

Filter multiple arrays with one condition

I have a tableView with different kinds of infos, each coming from a different array.
I could not work with dictionaries because then the list would have been unordered and I could not work with classes, because I have different lists with all kinds of dynamic entries (properties are always different etc.)
Here my problem:
I want to implement a search function. But when I use the filter function for one array, it changes of course based on the implemented condition but the other 5 stay the same => I can't reload the tableView because the array information does not match anymore ...
Here the arrays:
var categoryItemUIDs = [String]()
var categoryItemDescriptions = [String]()
var categoryItemLfdNrs = [Int]()
var categoryGivenOuts = [Bool]()
var categoryGivenTos = [String]()
var categoryGivenAts = [String]()
var categoryStorageLocations = [String]()
In the tableView(cellForRowAtIndexPath method):
cell.customTextLabel?.text = categoryItemLfdNrs[indexPath.row]
cell.customDetailTextLabel.text = categoryItemDescriptions[indexPath.row]
Here the searchBar(textDidChange) method:
self.categoryItemDescriptions.filter { $0.lowercased().contains(searchText.lowercased()) }
Now I get an array back with reduced size, but all the other arrays stay the same... Is there maybe another way to avoid this problem? I already tried type aliases but it did not work out.
I would appreciate any help!
Kind regards,
When it goes to such a big count of arrays, the time for your specific type comes.
The simple solution is to create something like
struct Category {
var uid: String
var description: String
// ...
var storageLocation: String
}
The you have simply something like
var items: [Category]
And you can still do simple things in cellForRowAtIndexPath
cell.customTextLabel?.text = items[indexPath.row].lfdnrs
cell.customDetailTextLabel.text = items[indexPath.row].description
And only 1 array to filter
items.filter { $0.description.lowercased().contains(searchText.lowercased()) }
So overall advice is to solve different problem (here I suggested the solution of the having your data in the app problem instead of filtering multiple arrays with one condition)
try
var categoryItemUIDs = ["aaa","bbb","ccc"]
var categoryItemDescriptions = ["ddd","eee","fff"]
var categoryItemLfdNrs = [0,1,2]
struct data {
var id = ""
var desc = ""
var item = 0
init(id :String, desc:String, item:Int)
{
self.id = id
self.desc = desc
self.item = item
}
}
//var cat = [data]()
//for i in 0..<categoryItemUIDs.count {
// cat.append(data(id:categoryItemUIDs[i], desc:categoryItemDescriptions[i],item:categoryItemLfdNrs[i] ))
//}
//more swift
let cat = (0..<categoryItemUIDs.count).map { (i) -> data in
return data(id:categoryItemUIDs[i], desc:categoryItemDescriptions[i],item:categoryItemLfdNrs[i] )
}
print (cat)
let catFilter = cat.filter { $0.id == "aaa" }
print (catFilter)

How to update swift dictionary value

I rewrite this code from php. And I find it difficult to make it work in swift.
var arrayOfData = [AnyObject]()
for index in 1...5 {
var dict = [String: AnyObject]()
dict["data"] = [1,2,3]
dict["count"] = 0
arrayOfData.append(dict)
}
for d in arrayOfData {
let data = d as AnyObject
// I want to update the "count" value
// data["count"] = 8
print(data);
break;
}
Presumably, you want to update the value inside of arrayOfData when you assign data["count"] = 8. If you switch to using NSMutableArray and NSMutableDictionary, then your code will work as you want. The reason this works is that these types are reference types (instead of value types like Swift arrays and dictionaries), so when you're working with them, you are referencing the values inside of them instead of making a copy.
var arrayOfData = NSMutableArray()
for index in 1...5 {
var dict = NSMutableDictionary()
dict["data"] = [1,2,3]
dict["count"] = 0
arrayOfData.addObject(dict)
}
for d in arrayOfData {
let data = d as! NSMutableDictionary
data["count"] = 8
print(data)
break
}
Assuming your array has to be of form '[AnyObject]' then something like this:
var arrayOfData = [AnyObject]()
for index in 1...5 {
var dict = [String: AnyObject]()
dict["data"] = [1,2,3]
dict["count"] = 0
arrayOfData.append(dict)
}
for d in arrayOfData {
// check d is a dictionary, else continue to the next
guard let data = d as? [String: AnyObject] else { continue }
data["count"] = 8
}
But preferably your array would be typed as an array of dictionaries:
var arrayOfData = [[String: AnyObject]]()
for index in 1...5 {
var dict = [String: AnyObject]()
dict["data"] = [1,2,3]
dict["count"] = 0
arrayOfData.append(dict)
}
for d in arrayOfData {
// swift knows that d is of type [String: AnyObject] already
d["count"] = 8
}
EDIT:
So the issue is that when you modify in the loop, you're creating a new version of the dictionary from the array and need to transfer it back. Try using a map:
arrayOfData = arrayOfData.map{ originalDict in
var newDict = originalDict
newDict["count"] = 8
return newDict
}
The most efficient way would be to find the index of the relevant values entry, and then replace that entry. The index is essentially just a pointer into the hash table, so it's better than looking up by key twice:
To update all the entries, you can loop through the indices one at a time:
for i in dictionary.values.indices {
dictionary.values[i].property = ...
}
To update a particular key, use:
let indexToUpdate = dictionary.values.index(forKey: "to_update")
dictionary.values[i].property = ...

How to convert from a Swift String Set to an Array

I am trying to create an array of words from a string object retrieved from Parse. The object retrieved looks like this:
Then this line of code gives this.
let joinedWords = object["Words"] as! String
How do I convert joinedWords to an Array?
If you don't care about the order, you can use flatMap on the set:
var mySet = Set<String>()
for index in 1...5 {
mySet.insert("testwords\(index)")
}
let myArray = mySet.flatMap { $0 }
print(myArray) // "["testwords5", "testwords3", "testwords4", "testwords2", "testwords1"]"
If you want the list sorted alphabetically, you can make your array a var and use sortInPlace()
var myArray = mySet.flatMap { $0 }
myArray.sortInPlace()
print(myArray) // "["testwords1", "testwords2", "testwords3", "testwords4", "testwords5"]"
If object["Words"] is AnyObject, you will have to unwrap it.
if let joinedWordsSet = object["Words"] as? Set<String> {
var joinedWordsArray = joinedWordsSet.flatMap { $0 }
myArray.sortInPlace()
print(myArray)
}
Swift 3 note: sortInPlace() has been renamed sort().
Many thanks to #JAL for so much time on chat to solve this one. This is what we came up with. Its a bodge and no doubt there is a better way!
When uploading to Parse save the set as an array.
let wordsSet = (wordList?.words?.valueForKey("wordName"))! as! NSSet
let wordsArray = Array(wordsSet)
Then it saves to Parse - looking like a set, not an array or a dictionary.
let parseWordList = PFObject(className: "WordList")
parseWordList.setObject("\(wordsArray)", forKey: "Words")
parseWordList.saveInBackgroundWithBlock { (succeeded, error) -> Void in
if succeeded {
// Do something
} else {
print("Error: \(error) \(error?.userInfo)")
}
}
Then you can drop the [ ] off the string when its downloaded from Parse, and remove the , and add some "" and voila, there is an array that can be used e.g. to add to CoreData.
var joinedWords = object["Words"] as! String
joinedWords = String(joinedWords.characters.dropFirst())
joinedWords = String(joinedWords.characters.dropLast())
let joinedWordsArray = joinedWords.characters.split() {$0 == ","}.map{ String($0) } // Thanks #JAL!

how to change my String Value into Array by removing "()"

Let say I have values like this
Apple(100)
Orange(300)
Pineapple(10)
Grape(50)
Banana(1000)
What I want to do is to create an array which was like that to each string
["Apple","100"]
["Orange","300"]
What i tried was like that,but it doesn't meet my answer well enough
var myNewFruits = "Apple(200)"
var newStr = myNewFruits.componentsSeparatedByString("(")
The Output was
["Apple","200)"]
What i really want was
["Apple","200"]
Is there any help with Swift?Thank you.Because I am creating search with that,so,i really need it.
You can use a custom NSCharacterSet and get the first two elements from the returned array:
let myNewFruits = "Apple(200)"
let newStr = myNewFruits.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "()"))[0...1] // ["Apple", "200"]
You can do it this way:
func stringToArr(str: String) -> [String] {
var newArr = [String]()
var fullNameArr = split(str) {$0 == "("}
newArr.append(fullNameArr[0])
var last: String? = fullNameArr.count > 1 ? fullNameArr[1] : nil
newArr.append(last!.stringByReplacingOccurrencesOfString(")", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil))
return newArr
}
var string = "Apple(100)" //"Apple(100)"
let newArr = stringToArr(string) //["Apple", "100"]

Resources