Reputation: 3561
Here's what I am trying to do:
I am starting with an array of ArticleItem objects. Those objects have a property on them named 'category' which is a string. I'm trying to loop through all of my ArticleItem objects and group items with like categories in a dictionary. I'm using the category name as my key. The issue I am having is that my dictionary keys are hold arrays that never contain more than 1 object. I definitely have more than 3 objects with the same category name. Here is the relevant code from my class. I'd love to understand the right way to do this..
private var _articlesDict:[String:[ArticleItem]]
init(articles:[ArticleItem]) {
_articlesDict = [String:[ArticleItem]]()
for item:ArticleItem in articles {
var optionalCatArray:[ArticleItem]? = _articlesDict[item.category]
if let catArray = optionalCatArray {
optionalCatArray!.append(item) //why can't I do catArray.append(item)?
} else {
var arr:[ArticleItem] = [ArticleItem]()
arr.append(item)
_articlesDict[item.category] = arr
}
}
}
Upvotes: 0
Views: 1776
Reputation: 385870
As an alternative to the native-array solutions in other answers, you could do this:
var _articlesDict = [String:NSMutableArray]()
init(articles:[ArticleItem]) {
for item:ArticleItem in articles {
if let array = _articlesDict[item.category] {
array.addObject(item)
} else {
_articlesDict[item.category] = NSMutableArray(object:item)
}
}
}
But keep in mind you'll have to cast to ArticleItem
when you extract items from the arrays in the dictionary.
Upvotes: 0
Reputation: 72760
The problem is that arrays are value types, so they are passed by value and not by reference. That means that every time you assign a variable holding an array to another variable (or array, or dictionary) you actually create a copy of it. But there's more.
1st problem
This line of code:
if let catArray = optionalCatArray {
creates an immutable copy of optionalCatArray
, so it cannot be modified. Use this instead:
if optionalCatArray != nil {
2nd problem
This line of code:
var optionalCatArray:[ArticleItem]? = _articlesDict[item.category]
creates a copy of the array stored in the dictionary - here:
if optionalCatArray != nil {
optionalCatArray!.append(item)
assign a new item to the array, but remember: this is a copy, so you are not modifying the array contained in the dictionary. What's missing is setting it back into the dictionary:
if optionalCatArray != nil {
optionalCatArray!.append(item)
_articlesDict[item.category] = optionalCatArray!
}
Probably this code can be improved by avoiding the array copy like this:
if _articlesDict[item.category] != nil {
_articlesDict[item.category]!.append(item)
} else {
_articlesDict[item.category] = [item]
}
I haven't tested it, but conceptually it should work. Also note how I shortened the else
branch, easier to read.
Upvotes: 1
Reputation: 4676
You cannot edit an array in a dictionary directly. You append to a local copy only.
See https://stackoverflow.com/a/24251066/1183577 for more info.
Upvotes: 0