4

Is there a way of simplifying this loop where i replaces whitespace with dashes for each item in a list?

for item in a_list:
    alist[alist.index(item)] = '-'.join(item.split(" "))

or is this better?

for item in a_list:
    alist[alist.index(item)] = item.replace(" ", "-")

NOTE: The above solution only updates the 1st occurrence in this list, as David suggested, use list comprehension to do the above task.

I have a list of words and some have dashes while some doesn't. The items in a_list looks like this:

this-item has a-dash
this has dashes
this should-have-more dashes
this foo
doesnt bar
foo
bar

The output should look like this, where all items in list should have dashes instead of whitespace:

this-item-has-a-dash
this-has-dashes
this-should-have-more-dashes
this-foo
doesnt-bar
foo
bar
5
  • 2
    both of your solutions won't work if you have duplicate items in your list since .index returns the first index of an item. Commented Sep 18, 2012 at 23:56
  • noted jamylak, david's list comprehension solution is the pythonic way to manipulate a list Commented Sep 19, 2012 at 0:08
  • 1
    Even though using a list comprehension is more Python, and usually simpler, and more flexible, it's still worth understanding how you can manipulate a list in-place without the index problems, because at some point that will come up. Commented Sep 19, 2012 at 0:14
  • 1
    @jamylak: Actually, in this case index would work. Once the first of multiple duplicates has been changed once, later duplicates won't try to replace it (or more precisely, if they do try to replace it, it means the duplicate string never had any spaces in it). So this is a rare case where index would work (although it is still not the best solution!!) Commented Sep 19, 2012 at 0:34
  • @DavidRobinson Aah i see you are correct Commented Sep 19, 2012 at 3:29

2 Answers 2

8

Use a list comprehension:

a_list = [e.replace(" ", "-") for e in a_list]
Sign up to request clarification or add additional context in comments.

Comments

2

When you find yourself using the index method, you've probably done something wrong. (Not always, but often enough that you should think about it.)

In this case, you're iterating a list in order, and you want to know the index of the current element. Looking it up repeatedly is slow (it makes an O(N) algorithm O(N^3))—but, more importantly, it's fragile. For example, if you have two identical items, index will never find the second one.

This is exactly what enumerate was created for. So, do this:

for i, item in enumerate(a_list):
    alist[i] = '-'.join(item.split(" "))

Meanwhile, you could replace the loop with a list comprehension:

a_list = ['-'.join(item.split(" ")) for item in a_list]

This could be slower or use more memory (because you're copying the list rather than modifying it in-place), but that almost certainly doesn't matter (it certainly won't be as slow as your original code), and immutable algorithms are simpler and easier to reason about—and more flexible; you can call this version with a tuple, or an arbitrary iterable, not just a list.

As another improvement, do you really need to split and then join, or can you just use replace?

a_list = [item.replace(" ", "-") for item in a_list]

You could use regular expressions instead, which might be better for performance or readability in some similar cases—but I think in this case it would actually be worse. So, once you get here, you're done.

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.