simplycoding
simplycoding

Reputation: 2977

How do I iterate through a dict while also removing newline characters?

I'm trying to iterate through a dictionary and remove newline characters, and having difficult with parsing the items.

Say we have

line_contents = {"user_id": "6GrH6gp09pqYykGv86D6Dg", "text": "Decent selection of more than just bar food. \n\nJumbo fish sandwich is aptly named. \n\nSeem to be generous with the pour.", "business_id": "fNGIbpazjTRdXgwRY_NIXA", "likes": 0, "date": "2013-04-22", "type": "tip"}

#I've tried:
line_contents=dict(map(strip(),x) for x in line_contents.items())
#but ^ doesn't work. I can't figure out how the map function or the dictionary comprehension works

#I eventually want:
line_contents = {"user_id": "6GrH6gp09pqYykGv86D6Dg", "text": "Decent selection of more than just bar food. Jumbo fish sandwich is aptly named. Seem to be generous with the pour.", "business_id": "fNGIbpazjTRdXgwRY_NIXA", "likes": 0, "date": "2013-04-22", "type": "tip"}

I'm tempted to iterate through the dictionary elements with a typical for loop but would like to try dict comprehension as I never have.

Upvotes: 0

Views: 849

Answers (2)

zondo
zondo

Reputation: 20346

Actually, you aren't using a dictionary comprehension. That is a function call with a single argument: a generator expression. A dictionary comprehension would be more like this:

line_contents = {key: value.replace("\n", "") for key, value in line_contents.items()}

Edit: niemmi made a good point that the values are not all strings. Therefore, you should use something similar to his suggestion:

line_contents = {k: v.replace("\n", "") if isinstance(v, basestring) else v for k,v in line_contents.items()}

I used basestring instead of niemmi's str because they are actually unicode. In Python 3, you should use str.

What was wrong with yours? Well, you are giving dict one argument. Consider this:

argument = []
for x in line_contents.items():
    argument.append(map(strip(), x))

line_contents = dict(argument)

That is pretty much what you are doing. For each key-value pair, you are giving map() two arguments strip() and x. For one call of map(strip(), x), you are in effect doing this:

function = strip()
result = []
for item in x:
    result.append(function(item))

Now you must see the problem. For one thing, strip is not defined. For another thing, you are supposed to supply map with a function, not what the function returns. If you wanted to use str.strip, do it like this:

map(str.strip, x)

The problem with that is that str.strip() strips from the ends; it does not remove the new lines that appear in the middle.

Upvotes: 4

niemmi
niemmi

Reputation: 17263

You can use dict comprehension but since some of your values are not strings you have to take that into account:

line_contents = {k: v.replace('\n', '') if isinstance(v, str) else v for k, v in line_contents.items()}

In case both keys and values contain newline you can use dict builtin:

line_contents = dict([y.replace('\n', '') if isinstance(y, str) else y for y in x] 
                     for x in line_contents.items())

Of course dict comprehension would still work but it would look quite messy:

line_contents = {k: v for k, v in
                 ([y.replace('\n', '') if isinstance(y, str) else y for y in x]
                  for x in line_contents.items())
                 }

Upvotes: 3

Related Questions