0

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
        }
    }
}

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.