## Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

### Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

# Better way to solve this Python Code Challenge?

It took me awhile to solve this Code Challenge. Finally did (yay!) but I have a feeling my solution isn't very elegant. Suggestions welcome!

```def word_count(my_string):
my_string = my_string.lower()
word_list = my_string.split()
word_dict = {}
count = 0
for word in word_list:
if word in word_dict:
count = word_dict[word]
count += 1
word_dict.update({word: count})
else:
word_dict[word] = 1
return word_dict
```

```def word_count(my_string):
my_string = my_string.lower()
word_list = my_string.split()
word_dict = {}
count = 0 # You don't really need this outside of the for loop
for word in word_list:
if word in word_dict:
count = word_dict[word] # Instead of doing all of this
count += 1 # you can increment the value for that key
word_dict.update({word: count}) # directly - word_dict[word] += 1
else:
word_dict[word] = 1
return word_dict
```

So that would turn into:

```def word_count(my_string):
my_string = my_string.lower()
word_list = my_string.split()
word_dict = {}
for word in word_list:
if word in word_dict:
word_dict[word] += 1
else:
word_dict[word] = 1
return word_dict
```

If you want to make it even shorter, you can get rid of the `word_list` variable and iterate over the return value of the chained `.lower().split()` method call:

```def word_count(my_string):
word_dict = {}
for word in my_string.lower().split():
if word in word_dict:
word_dict[word] += 1
else:
word_dict[word] = 1
return word_dict
```

Hi Ryan,

You can increment the count in your `if` block like this: `word_dict[word] += 1`

This would grab the current count for that key, add one to it and store it back in that same key.

This can replace the 3 lines you have in your `if` block.

You can then remove the `count` initialization before the `for` loop.

Hi Ryan,

Going off Jason's answer which is the same thought process I had you can shorten your code all the way down to...

```def word_count(my_string):
word_dict = {}

for word in my_string.split():
if word in word_dict:
word_dict[word] += 1
else:
word_dict[word] = 1

return word_dict
```
STAFF

Since we talked about this in work chat, I'll post my two alternate solutions. Let's assume this string for all examples:

```sentence = "If the facts don't fit the theory change the facts"
```

### Using `Counter`

So Python has this library named `collections` that stores a lot of alternate collection types. One of those is `Counter` which, well, counts things.

```from collections import Count

def word_count(my_string):
words = my_string.lower().split()
counts = Counter(words)
return counts
```
```>>> output = word_count(sentence)
Counter({'if': 1, 'the': 3, ...})
```

What's really awesome about `Counter`, though is being able to do this:

```>>> output.most_common(1)
[('the', 3)]
```

### Using `setdefault`

Python's `dict` object has a weird (to me) method called `setdefault()` that let's you set a default value if the dict doesn't have the key you want. Otherwise it returns the value of the key. Say:

```>>> my_dict = {'a': 5}
>>> my_dict.setdefault('a', 10)
5
>>> my_dict.setdefault('b', 10)
10
>>> my_dict
{'a': 5, 'b', 10)
```

So you can use that for `word_count()`

```def word_count(my_string):
words = my_string.lower().split()
counter = {}
for word in words:
counter[word] = counter.setdefault(word, 0) + 1
return counter
```

The `counter[word] = counter.setdefault(word, 0) + 1` line trips some people up. We're setting the default to 0 and then incrementing it by 1. Basically we've negating the `try`/`except` that's needed for the usual approach.

So why didn't I teach either of these methods? They're way more special-case than using `try/`except`and`.get()` and the like. I'd rather you have common scenario tools than wizzbang special effect tools. But, I guess you can now consider yourself taught these nifty little tools. Be sure to check out collections if you want more neat tools.

Thank you sir! :)

Mr. Love;

That is too cool. Didn't know about that in Python.

Mr. Carson;

It is also pretty cool to see you on here sharing the same "struggles" the rest of us have.

Keep up the awesome content, gentlemen.

Ken