2

Right now, I am struggling to find a proper answer. Let's say we have this list:

['12', '50', '12', '7', '7', '3', '4', '10', '19', '12']

As you can see, it's a list of strings. I could map this to a list of ints, but I won't, because I need to change them back to strings anyway. On the other hand, it would be handy if I would do it because I need to check for a condition.

What do I need? --> I need to change the elements in the list when a certain condition is met. So, for example: if a list in the element is greater than 10, I need to change the element to a certain character like a plus (+) or a minus (-)

Eventually, my list should be something like this:

['+', '+', '+', '-', '-', '-', '-', '+', '+', '+']

So, the concept in my head right now is:

  • Don't convert the string to an int, because I will need to transform them to strings anyway (hence the special characters I was talking about).

  • I need to use a for loop, because I want to check every element

I'd probably need to use a loop like this:

for score in scores:
   if score == "5": # check if element is a 5
      score == "+"  # make it a plus
   else:
      score == "-"  # make it a minus

Problem: this doesn't work and I don't even know if this is the right way. I can use score[0] and get every element in the list like this, but this wouldn't be efficient nor generic, or would it? What is the best way to transform elements in a list when a certain condition is met?

Can someone point in me the right direction please?

Siyah
  • 2,852
  • 5
  • 37
  • 63

3 Answers3

10

Try this (assuming you want 10 as the cutoff)

li = ['12', '50', '12', '7', '7', '3', '4', '10', '19', '12'] 

new_list = ['+' if int(el)>10 else '-' for el in li]
Leo
  • 1,773
  • 12
  • 19
  • This assumes the OP doesn't need to make changes to the existing list. – Scott Hunter Nov 23 '16 at 16:25
  • not exactly newbie-friendly but that is the way to do it. – Ma0 Nov 23 '16 at 16:25
  • But this isn't generic? What would happen if my list would change? I don't like non-generic solutions, but thanks anyway! – Siyah Nov 23 '16 at 16:26
  • 1
    What do you mean not generic? – Ganesh Kathiresan Nov 23 '16 at 16:27
  • @Siyah: Waht made you think it is not generic? Infact, it is the ideal way to achieve it – Moinuddin Quadri Nov 23 '16 at 16:27
  • 2
    @Siyah What do you mean by that? the `new_list` definition takes whatever is in the `li` and works with that. Nothing is hard-coded here. And if you need to modify the list **in place** (not create an additional one that is) just change the `new_list` to `li`. – Ma0 Nov 23 '16 at 16:28
  • I think I got it, but... this assumes the elements in the list are ints, but they are not. So I should map them to an int first in that case? – Siyah Nov 23 '16 at 16:29
  • 1
    @Siyah It does not. it does the conversion only for checking the condition. This is what makes it different from the solution posted by **Ganesh**. – Ma0 Nov 23 '16 at 16:30
  • Ahhhh! I see it now. Yes, damn. Foolish. Thanks man! – Siyah Nov 23 '16 at 16:31
  • Can I ask a question btw? Can someone explain to me how the tranformation precisely happens? Because I don't understand where it changes it... because when I would write down this same loop on multiple lines (properly), I can't get it working. It just changes the whole list to a plus or a minus... – Siyah Nov 23 '16 at 16:55
  • @Siyah, AFAIK looping through a list like `for score in scores:` and then trying to alter `score` inside the loop will not change the original list, `scores` – Leo Nov 23 '16 at 17:03
  • But isn't yours doing the same? You have a for loop... I don't get how it's transformed here... – Siyah Nov 23 '16 at 17:06
  • No, mine is using [list comprehension](http://www.secnetix.de/olli/Python/list_comprehensions.hawk) which works by creating a new list (in memory) rather than altering the existing list. From there you can do whatever you want with it such as assign it to a new variable (like my example) or assign it to an existing variable. – Leo Nov 23 '16 at 17:59
1

It doesn't work because:

  1. A for loop in Python creates a new local variable, and

  2. You used == instead of =.

Try this approach:

for index, score in enumerate(scores):
   if scores[index] == "5": # check if element is a 5
      scores[index] = "+"  # make it a plus
   else:
      scores[index] = "-"  # make it a minus

A quick side note: your question asks for "greater/smaller" then but your example uses ==. If you want to test for greater or smaller you have to convert the elements to int.

DeepSpace
  • 78,697
  • 11
  • 109
  • 154
  • `i` is not the same thing as `index`. And what's the point of using `enumerate` if you aren't going to use the extracted values? – Scott Hunter Nov 23 '16 at 16:23
  • @ScottHunter thanks, fixed that – DeepSpace Nov 23 '16 at 16:24
  • 1
    You don't use `score` so `enumerate` is not nedt. `for index in range(len(scores)):` – Adirio Nov 23 '16 at 16:26
  • @Adirio Using `range(len(scores))` is considered to be less Pythonic. – DeepSpace Nov 23 '16 at 16:27
  • 1
    @DeepSpace lol no, using a method only available in Python doens't mean you are more pythonic, your solution is less efficient in both time and resources – Adirio Nov 23 '16 at 16:28
  • Thanks DeepSpace, I appreciate your help and upvoted. I do think that Leo's solution is more efficient though. – Siyah Nov 23 '16 at 16:31
  • @Adirio Deespace is right in my opinion. What you see people do often when (as here) the item itself is not needed is something like `for index, _ in enumerate(scores):`. They use an underscore to show that this will not be used. – Ma0 Nov 23 '16 at 16:34
  • @Ev.Kounis The underscore usage as a "this won't be used" is actually quite pythonic, yes, same as enumerate and range methods. I would have to further inspect it but I think range is more resource-eficient in Python3 (range used to be a function returning a list while enumerate returned an iterator in Python2 but while enumerate behaviour has not changed range has, and now it returns a range object that only keeps start, end and step in memory https://docs.python.org/3/library/stdtypes.html#typesseq-range) – Adirio Nov 24 '16 at 08:08
1

You can do:

  1. Initial l = ['12', '50', '12', '7', '7', '3', '4', '10', '19', '12']
  2. Map to int: l = list(map(int, l))
  3. Then: a = ['+' if i>10 else '-' for i in l]
  4. a = ['+', '+', '+', '-', '-', '-', '-', '-', '+', '+']
Ganesh Kathiresan
  • 2,068
  • 2
  • 22
  • 33