Swift: Get max value for key in array of dictionaries - swift

I have an array containing dictionaries.
let arr = [["test":1], ["test":2], ["test":3], ["test":4]]
I now need to get the one dictionary that contains the highest value for the key "test" (without iterating through everything). I was thinking about filter(_:) but this will only filter out. map(_:) also does not work as I need to filter and not to map.
There's an example how to get the key with the highest value in a dictionary but this does not work in this case.
let hues = ["Heliotrope": 296, "Coral": 16, "Aquamarine": 156]
let greatestHue = hues.max { a, b in a.value < b.value }
print(greatestHue)
Any help is appreciated!

You can use max much like in your example.
let arr = [["test":1], ["test":4], ["test":3], ["test":2]]
print(arr.max { $0["test"]! < $1["test"]! })
This gives the dictionary with the highest value.
Of course the use of ! is bad unless it is guaranteed that each dictionary really has a "text" key.
Also note that using max will still result in the entire array being iterated. You can't avoid that unless your dictionaries are always sorted by the value. Then in that case simply use last instead of max.

Related

suffix array Index out of bounds

I have an array , when I suffix array and want to select element , I get error: Index out of bounds.
But when I prefix array and select element, It's sucess.
How should I do that I can select after suffix array?
Here is code:
let array = [1,2,3,4,5,6,7,8,9,10]
let suffixArray = array.suffix(5)//[6,7,8,9,10]
let prefixArray = array.prefix(5)//[1,2,3,4,5]
print(suffixArray[2])//Index out of bounds
print(prefixArray[2])//sucess print "3"
The problem you are having is that with .suffix the array does not start with 0. So if you wanted to print the 3rd number in the suffix array, you would have to call print(suffixArray[7].
If you read the description for the return value here. It reads:
A subsequence terminating at the end of the collection with at most maxLength elements.
And if you read the description to subsequence:
A collection representing a contiguous subrange of this collection’s elements. The subsequence shares indices with the original collection.
Full example for playground:
let array = [1,2,3,4,5,6,7,8,9,10]
let suffixArray = array.suffix(5) // [6,7,8,9,10]
let prefixArray = array.prefix(5) // [1,2,3,4,5]
var newSuffixArray: [Int] = []
for i in suffixArray {
newSuffixArray.append(i)
}
print(suffixArray[7]) // 8
print(newSuffixArray[2]) // 8
print(prefixArray[2]) // 3
Both prefix and suffix return an ArraySlice rather than another Array.
Here's an excerpt from the ArraySlice documentation:
Unlike Array and ContiguousArray, the starting index for an
ArraySlice instance isn’t always zero. Slices maintain the same
indices of the larger array for the same elements, so the starting
index of a slice depends on how it was created, letting you perform
index-based operations on either a full array or a slice. Sharing
indices between collections and their subsequences is an important
part of the design of Swift’s collection algorithms.
You can see that by looking into the indices property of prefixArray and suffixArray.
Generally you are encouraged to use methods of accessing elements that collections provide instead of assuming values of indices.

Sort and combine elements to be unique

I have a bunch of tokens stored in combinedCoinsFromAllWalles and I'm sorting them by who contains the largest monetary value like this:
let sortedCoins = combinedCoinsFromAllWalles.sorted() { Double($0.token!.quote!) > Double($1.token!.quote!) }
The problem is that some tokens are repeated by name, for example, on that sorting I could have 2 tokens with the same name on $0.token!.name
What would be the most efficient way to also combine those similar tokens and add their value? Something like this:
token A (named BTC)
token B (named BTC)
token C (named ETH)
I want to sum token A and B quote ($0.token!.quote! + $0.token!.quote!) while filtering.
How do I do that in the most efficient way?
That first sort in your example is a waste since you have not combined all the different sources for similar coins first and the order may then change.
You should:
Aggregate coin values
Sort by desired order
One simple way to do this would be to create a dictionary, adding new coins or summing totals as you iterate through your data. Then convert the dictionary back to an array and sort how you would like.
Ex:
var dict: [String: Float] = []
for each in combinedCoinsFromAllWalles {
if dict.contains(each.token) {
dict[each.token] += each.quote
}else{
dict[each.token] = each.quote
}
}
let sortedCoinValueArray = dict.sorted(by: $0.1 < $1.1)
The resulting array is an array of key-value pairs, so you may iterate over it like this:
for (key, value) in sortedCoinValueArray {
print("${key}: ${value}"
}

How can I sort dictionary by an array guide when I have order keys?

How can I sort a dictionary by key if I have a second array guide where I had all sorted key of dictionary?
Example:
let dict = ["35": "a", "398":"b", "98":"c"]
let guideArray = ["398","35","98"]
so I want a sorted dict like:
let sortDict = ["398": "b", "35":"a", "98":"c"]
A dictionary is not a sorted type of table by definition so cannot be sorted and nothing ensures that the order of the elements won't change. I don't think is the best approach.
You could make an array and add the elements there if what matters for you is the order.

Get position as int from Set<>.index in Swift

I have a set collection and I want to get index of an element. I'm using firstIndex function of set but It returns Set.index. How can I convert it to int?
let index = mySet.firstIndex(of: dataSource) // This returns Set<>.index
Set.index Documentation
Set is unordered, try using an Array for example
It is very easy to convert a set index to an int
index.hashValue
however you will find that that index isn't very useful
Set(["a", "b", "c"]).firstIndex(of: "a")?.hashValue
// 5346078814578125500
this is because a set uses a hash table as its underlying storage mechanism. You'll see this if you try to print the index itself
Index(_variant: Swift.Set<Swift.String>.Index._Variant.native(Swift._HashTable.Index(bucket: Swift._HashTable.Bucket(offset: 3), age: -233657665)))
What firstIndex returns to you is simply the hashkey at which that element is stored. It does not relate to any kind of "position" because hash tables don't have a meaningful sense of position.

Ordering of Dictionary Swift

I'm trying to work through a problem at the moment which is currently doing the rounds on the internet. The problem is: Given an array of characters, find the first non repeating character. I had a go at it and solved it but I was curious about how other people solved it so I did some looking around and found this answer:
let characters = ["P","Q","R","S","T","P","R","A","T","B","C","P","P","P","P","P","C","P","P","J"]
var counts: [String: Int] = [:]
for character in characters {
counts[character] = (counts[character] ?? 0) + 1
}
let nonRepeatingCharacters = characters.filter({counts[$0] == 1})
let firstNonRepeatingCharacter = nonRepeatingCharacters.first!
print(firstNonRepeatingCharacter) //"Q"
Source: Finding the first non-repeating character in a String using Swift
What I don't understand about this solution, is why it always returns Q, when there are other elements "S" "A" "B" and "J" that could be put first when the filter is applied to the dictionary. My understanding of dictionaries is that they are unordered, and when you make one they change from run to run. So if I make one:
let dictionary:[String:Int] = ["P": 9, "C": 8, "E": 1]
And then print 'dictionary', the ordering will be different. Given this, can anyone explain why the solution above works and maintains the order in which the dictionary elements were added?
You are not looking correctly at the code. The filter is not applied to a dictionary. It is applied to the array (characters), which has a defined order. The dictionary is used only to store counts.