I need to write a dictionary to a text file. I couldn't find anything handy. But writing an array is solved only for strings:
let pieces = [ "1", "5", "1", "4" ]
let joined = "\n".join(pieces)
How could I join integers without creating my own loop?
If there is a simple solution for dictionary itself, that would be better! ;-)
So you have an array of Int
let numbers = [1,2,3,4,5]
And you want to concatenate the text representations of these numbers without writing a loop right?
You can write this:
let joined = "\n".join( numbers.map { "\($0)" } )
Now joined has this value: "1\n2\n3\n4\n5"
Hope this helps.
Related
I have an array that is storing a large number of various names in string format. There can be duplicates.
let myArray = ["Jim","Tristan","Robert","Lexi","Michael","Robert","Jim"]
In this case I do NOT know what values will be in the array after grabbing the data from a parse server. So the data imported will be different every time. Just a list of random names.
Assuming I don't know all the strings in the array I need to find the index of the last occurrence of each string in the array.
Example:
If this is my array....
let myArray = ["john","john","blake","robert","john","blake"]
I want the last index of each occurrence so...
blake = 5
john = 4
robert = 3
What is the best way to do this in Swift?
Normally I would just make a variable for each item possibility in the array and then increment through the array and count the items but in this case there are thousands of items in the array and they are of unknown values.
Create an array with elements and their indices:
zip(myArray, myArray.indices)
then reduce into a dictionary where keys are array elements and values are indices:
let result = zip(myArray, myArray.indices).reduce(into: [:]) { dict, tuple in
dict[tuple.0] = tuple.1
}
(myArray.enumerated() returns offsets, not indices, but it would have worked here too instead of zip since Array has an Int zero-based indices)
EDIT: Dictionary(_:uniquingKeysWith:) approach (#Jessy's answer) is a cleaner way to do it
New Dev's answer is the way to go. Except, the standard library already has a solution that does that, so use that instead.
Dictionary(
["john", "john", "blake", "robert", "john", "blake"]
.enumerated()
.map { ($0.element, $0.offset) }
) { $1 }
Or if you've already got a collection elsewhere…
Dictionary(zip(collection, collection.indices)) { $1 }
Just for fun, the one-liner, and likely the shortest, solution (brevity over clarity, or was it the other way around? :P)
myArray.enumerated().reduce(into: [:]) { $0[$1.0] = $1.1 }
i want from tableview to collect MyArray's as value like
Swift:
let total = UILabel()
var MyArray = ["2", "9", "33", "4"]
total.text = ?? // i want result be like this [2+9+33+4] = 48
and if add some value or remove some the result change
i hope i delivered right question and i hope i get the right answer
Iterate through your array, using conditional binding, if the value is invalid, e.g "hello", it won't enter the condition.
var result = 0
for element in MyArray { // MyArray should have the first letter lowercased and have a more meaningful name.
if let number = Int(element) { // or NSNumber, Double, etc...
result = result + number
}
}
total.text = "\(result)" // consider naming it totalLabel
Convert the myArray elements type from String to Double using compactMap. Then add the elements using reduce method. Then convert the result to string to show in label.
var myArray = ["2", "9", "33", "4", "wot?", "🐶"]
total.text = String(myArray.lazy.compactMap{ Double($0) }.reduce(0, +))//48.0
Two suggestions:
With reduce to sum up the values and ignore non-integer values
total.text = String(myArray.reduce(0, {$0 + (Int($1) ?? 0)}))
With NSExpression if the array contains only string representations of integers. joined converts the array to "2+9+33+4"
let additionExpression = NSExpression(format: myArray.joined(separator: "+"))
total.text = "\(additionExpression.expressionValue(with: nil, context: nil)!)"
There are two steps::
Calculate the total.
Consider:
let array = ["200", "900", "33", "4"]
let total = array
.lazy
.compactMap { Double($0) }
.reduce(0, +)
Note, unlike other suggestions, I’m refraining from placing this in a single line of code (although one could). The goal of functional programming patterns is to write expressive yet efficient code about which it is easy to reason. Placing all of this onto one line is contrary to that goal, IMHO, though it is arguably a matter of personal preference.
Setting the text of the label.
When setting the text of the label, it’s very tempting to want to just do String(total). But that is not a very user-friendly presentation (e.g. the sum 1,137 will be shown as “1137.0”). Nor is it localized.
The typical solution when displaying a result (whether numbers, dates, time intervals, etc.) in the user interface is to use a “formatter”. In the case of numeric values, one would typically use a NumberFormatter:
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
label.text = formatter.string(for: total)
For a user in the US, that will show “1,137”, whereas the German user will see “1.137”. So each device sees the number presented in a format consistent with the users’ localization preferences.
I am working with a string array that has about 1100 employee names.
I want to extract the first characters of the employee names so that i can divide the names in table view alphabetically and in different sections. Just like how the contacts app on iPhone does.
i tried this for extraction
var first_char = [String]()
while (i < employeenames.count)//employeenames is the names array
{
first_char.append(String(employeenames[i].prefix(1)))
i+=1
}
This way I am getting the desired characters but the code is taking really long. Also I want to count how many times "A" or "B" shows up in first_char array. Which is again taking another many seconds and smoking the CPU.
Please someone help me with this.
You seem to want to do a "group by" operation on the array of names.
You want to group by the first character, so:
let groups = Dictionary(grouping: employeenames, by: { String($0.first!).uppercased() })
The return value will be [Character: [String]].
To count how many times A shows up, just do:
groups["A"].count
Use this code:
let employeenames = ["Peter", "John", "Frank"]
let firstChars = employeenames.map { String($0.first ?? Character("")) }
The order of the resulting single-character array will be the same as the order of the employeenames array. If you need sorting:
let sortedFirstChars = firstChars.sorted()
Given
let employee: [String] = ["James", "Tom", "Ben", "Jim"]
You can simply write
let firstCharacters = employee.compactMap { $0.first }
Result
print(firstCharacters)
["J", "T", "B", "J"]
Sorting
If you want the initial characters sorted you can add this line
let sortedFirstCharacters = firstCharacters.sorted()
["B", "J", "J", "T"]
Occurrencies
let occurrencies = NSCountedSet(array: firstCharacters)
let occurrenciesOfJ = occurrencies.count(for: Character("J"))
// 2
I have two arrays of strings that I join together with a "-" separator which turns it into a full string like so "art-movies-sports". The code is below:
let myFirstArray: [String] = ["art", "movies", "sports"]
let firstJoinedArray = myFirstArray.joined(separator: "-")
let mySecondArray: [String] = ["art", "movies", "sports"]
let secondJoinedArray = mySecondArray.joined(separator: "-")
What I want is to call something when 3 or more words from "art-movies-sports" in firstJoinedArray are equal to 3 or more words in secondJoinedArray. In this case, it will of course be correct. In a nutshell, I want to have much longer strings (both containing different words but have 3 or 4 that are the same) and I want to call something when 3 or more are correct. Any help will be much appreciated! Thank you.
I would use the arrays directly, rather than the string. Then create sets out of them, so you can find their intersection:
let set1 = Set(myFirstArray)
let set2 = Set(mySecondArray)
let inCommon = set1.intersection(set2).count // If this is >= 3, do stuff
G'day,
I'm trying to use a for loop to access the values for the same key within an array of dictionaries in Swift.
For example,
let dictionaryOne = [
"name": "Peter",
"age": "42",
"location": "Milwaukee"]
let dictionaryTwo = [
"name": "Paul",
"age": "89",
"location": "Denver"]
let arrayOfDictionaries = [dictionaryOne, dictionaryTwo]
I'm attempting to create a function using a for loop that will output an array containing the values for location i.e. ["Milwaukee", "Denver"]
I have looked at other responses but I can only find how to access the value for "location" straight from the dictionary itself, which would be cumbersome if there were many different dictionaries rather than just two.
Many thanks for any help you can provide!
You can take advantage of the map method, whose purpose is to loop through the array and transform each element into another type:
arrayOfDictionaries.map { (dict: [String : String]) -> String? in
return dict["location"]
}
The closure passed to the map receives an array element, and returns the transformed value - in your case, it retrieves and returns the value for the location key.
You can also use the compact form:
arrayOfDictionaries.map { $0["location"] }
Note that this method returns an array of optional strings, because the dictionary subscript operator always returns an optional. If you need an array of non optionals, then this is the unsafe version:
let x = arrayOfDictionaries.map { $0["location"]! }
Of course if the value for "location" key doesn't exist for an array element, a runtime exception will be raised.
More info about map at the Swift Standard Template Library
The way I see it, you would populate a new array of Strings from the cities listed before.
var locations = [String]()
for dictionary in arrayOfDictionaries{
locations.append(dictionary["location"]!)
}
println(locations)
There are a few ways you could do this. One is to use key-value coding (KVC):
let locations = (arrayOfDictionaries as NSArray).valueForKey("location") as [String]