Im attempting to to combine two swift arrays into a simple swift dictionary. I am extremely new to swift (but know a decent amount of python), and have come across something that I think is rather odd. When I run the code below, I get a dictionary just as expected, however, if I rerun the code, the key:value pairs come up in a different order. I know that dictionaries in swift are supposed to be unordered, but does this mean each time I go to iterate through the key:value pairs of a dictionary, the order of these pairings may change? In other words, is it impossible to preserve the order to the two initial arrays that comprise the dictionary in the final dictionary product?
let cities: Array<String> = ["Paris", "Mexico City", "Rome"]
let countries: Array<String> = ["France", "Mexico", "Italy"]
var newCountrydict : Dictionary<String, String> = [:]
for (city,country) in zip(cities,countries){
newCountrydict[country] = city
}
newCountrydict
In the swift docs, under "Dictionaries":
Unlike items in an array, items in a dictionary do not have a specified order. You use a dictionary when you need to look up values based on their identifier, in much the same way that a real-world dictionary is used to look up the definition for a particular word.
It is not possible to preserve the order if you use dictionaries in swift.
In the same docs, it says:
Arrays are ordered collections of values. Sets are unordered collections of unique values. Dictionaries are unordered collections of key-value associations.
I suggest you read through the official documents.
Related
I am trying to populate Json downloaded and populate them into an array of objects. However, there are some complexity on how the data is structured, how would I be able to populate those arrays into objects efficiently?
The following is the basic structure of the Json Data downloaded from a web service:
{
timestamp: [Date],
openingStockPrice: [Double],
closingStockPrice: [Double]
}
E.g.
{
timestamp: [2019-01-01, 2019-01-02, 2019-01-03....],
openingStockPrice: [100.0, 101.0, 95.0, ...],
closingStockPrice: [101.0, 95.0, 99.5, ...]
}
Based on the data structure, there are three separate arrays with data types of dates and double.
Therefore, the first item of each of the arrays belongs to the stock pricing for that particular date. The second item of each of the arrays belongs to the second day... etc.
Currently, I manage to loop through each of the array and populate the data into objects based on the following structure.
Struct StockPrice {
timestamp: Date,
openingStockPrice: Double,
closingStockPrice: Double
}
var stockPrice: [StockPrice]
I manage to organise the data into array of StockPrice objects by looping through each of the arrays separately. However, looping through each array does not seem efficient at all as the data set becomes large.
Would any one know, possibly, another way to populate multiple arrays into one array of StockPrice objects (in this scenario)?
Whatever you do, you would still have to iterate through your multiple arrays because you have to fetch each item. I doubt you can find a O(logN) solution because of the nature of the problem. The best is a O(n)
O(n) solution:
var stockPrices = [StockPrice]()
//assuming timeStamps, openingStockPrices, closingStockPrices have the same number of elements
for i in 0 ..< timeStamps.count {
let timeStamp = timeStamps[i]
let openingStockPrice = openingStockPrice[i]
let closingStockPrice = closingStockPrice[i]
let stockPrice = StockPrice(timeStamp, openingStockPrice, closingStockPrice)
stockPrices(add: stockPrice)
}
tbf, an O(n) is relatively fast
Hi I have a dictionary of type:
1:[[12.342,34.234],[....,...],....]
2:[[......],[....]]....
Now I'd like to know if there are functions to delete specifics key and correspondents value, and a function to re-index it for examples if I delete the value correspondents to key 2 the key 3 should become the key 2 and so on.
I think you need to use an Array, not a Dictionary
var elms: [[[Double]]] = [
[[0.1],[0.2, 0.3]],
[[0.4], [0.5]],
[[0.6]],
]
elms.remove(at: 1) // remove the second element
print(elms)
[
[[0.10000000000000001], [0.20000000000000001, 0.29999999999999999]],
[[0.59999999999999998]]
]
Yes output values are slightly different from the original ones.
To delete a key and value, just do dict[key] = nil.
As for re-indexing, dictionary keys are not in any particular order, and shifting all the values over to different keys isn't how a dictionary is designed to work. If this is important for you, maybe you should use something like a pair of arrays instead.
Dictionaries are not ordered. This means that "key 3" becoming "key 2" is not a supported scenario. If keys have been in the same order that you've inserted them, you've been lucky so far, as this is absolutely not guaranteed.
If you want ordering and your list of key/value pairs is small (a hundred or so is small), you should consider using an array tuples: [(Key, Value)]. This has guaranteed ordering. If you need something bigger than that or faster key lookup, you should find a way to define an ordering relationship between keys (such that you can say that one should always be after some other key), and use a sorted collection like this one.
I'm working to convert some of my ObjC code that uses primitive c arrays to Swift arrays. However, using a playground, I've found some strange behaviors.
For instance, the following is perfectly valid in Swift
var largearray : [[Float]] = []
largearray.append([0,1,2]) //3 elements
largearray.append([3,4,5]) //3 elements
largearray.append([6,7,8,9]) //-4- elements
largearray.append([10,11,12]) //3 elements
//pull those back out
largearray[1][0] //gives 3
largearray[1][2] //gives 5
//largearray[1][3] //error
largearray[2][0] //gives 6
largearray[2][2] //gives 8
largearray[2][3] //gives 9
largearray[3][0] //gives 10
I don't understand how it's possible to have a mixed row lengths is Swift. Can someone explain what's going on here, because the documentation doesn't go into that kind of detail. I'm curious if it is even storing a contiguous Float array behind the scenes or not.
Then another question I have is about accessing rows or columns. In Swift I see that I can access an entire row using largearray[0] gives [0,1,2], just as largearray[2] gives [6,7,8,9]. Which isn't how c arrays are indexed. (If I just specified one index for a 2D c-array, it would act as a sequential index row by column. So, is there some way to access an entire column in swift? In c, and Swift, largearray[][2] is invalid. But I'm curious if there is some technique not mentioned in the docs, since it seems obvious that Swift is keeping track of extra information.
I should add that I will be making use of the Accelerate framework. So if any of the above "strange" ways of using a Swift array will cause performance issues on massive arrays, let me know.
How are Swift arrays different than c arrays
In C, an array is always a contiguous list of elements. In Swift, an array is a much more abstract data structure. You can make assumptions about how data is organized in memory with a C array, and you can even calculate the addresses of an element given the base address, element size, and an index. In Swift, not so much. Think of Swift's Array type the same way you think of NSArray in Objective-C. It's an ordered sequence of elements that provides array-like operations, but you shouldn't worry about how it stores the actual data.
I don't understand how it's possible to have a mixed row lengths is Swift.
Well, for one thing, you're really looking at an array of arrays. If an array is an object, then an array of arrays is probably implemented as an list of object pointers rather than a contiguous series of same-sized lists. You can do the same thing with NSArray, for example, because each item in an NSArray can be an object of any type.
So, is there some way to access an entire column in swift?
You'd need to iterate over the items in the array, which are themselves arrays, and examine the element at the "column" position you're interested in. I don't think there's a faster way to do it than that.
How can a dictionary be sorted, by its keys, in the order listed in an array? See example:
Dictionary to sort:
var item = [
"itemName":"radio",
"description":"battery operated",
"qtyInStock":"12",
"countOfChildren":"5",
"isSerialized":"0"
]
Order in which the keys should be sorted:
let sortOrder = [
"itemName",
"qtyInStock",
"countOfChildred",
"description",
"isSerialized"
]
I have tried the following in Playground:
var sortedItem = Dictionary<String, String>()
for i in sortOrder {
sortedItem[i] = item[i]
}
While viewing the value history in Playground displays everything in the correct order, the resulting dictionary is in a seemingly random order.
As mentioned by Tiago, a Dictionary by definition doesn't have an order. It is essentially a mapping of keys to values. I would recommend one of two approaches.
If the ordering you wish to achieve is manual as your question makes it seem. I would create an array to hold ordered keys. Then, at any point you need to, you can cycle through the array (which is order) and print out all of the values found in the dictionary. They will inherently be printed out using the ordered array of keys.
If the ordering is something than be done programmatically, you could grab a reference to all of the keys by doing myDictionary.keys.array. You could then sort the array, then once again, iterate through the array and grab the values from the dictionary.
Example:
let myKeys = myDictionary.keys.array
// sort the keys
for key in myKeys {
println(myDictionary[key])
}
Hope that helps.
A dictionary, by definition, doesn't have an order.
However, you can have an array of sorted items by touples or implement your sorted dictionary.
How can I write a NSPredicate that will check if all the elements in an NSArray are the same? I need this for a more complex predicate that I am using to filter NSTableView.
NSPredicate can't tell you if all the items are the same, but you could use it to filter an array for objects that are not equal to object[0]. This wouldn't be particularly performant since it would have to check the entire contents of the array.
You could instead use - (void)enumerateObjectsWithOptions: then bailing out when you find a different object via *stop = YES.
Consider looking at using NSSet, since that is designed to store a collection of unique objects (albeit unordered).
Without knowing more detail it's impossible to say what is the best solution for you.