0

I am new to Python but have C/C++ background. I am trying to modify a 2D list (list of lists) elements that satisfy a condition. All I could come up with is the following solution:

tsdata = [[random.random() for x in range(5)] for y in range(5)]
def check(tsdata):
    for i in range(len(tsdata)):
        for j in range(len(tsdata[i])):
            if (tsdata[i][j] < min_value) or (tsdata[i][j]> max_value):
                tsdata[i][j] = 0
check(tsdata)

I am sure there is a better solution which is actually suitable for Python but can't think of anything else that actually works.

EDIT: Actually, the list tsdata is a function argument and I am trying to modify it so some of your answers do not work. I have edited the code so this is clear.

othymomo
  • 105
  • 1
  • 2
  • 7

3 Answers3

3

If you want to handle big arrays, you may want to use numpy. Besides being much more efficient, I think the code is easier to read:

from numpy import random
tsdata = random.random((5, 5))
tsdata[tsdata < min_value] = 0
tsdata[tsdata > max_value] = 0
Mikael Rousson
  • 2,247
  • 1
  • 15
  • 16
0

Welcome to the world of simplicity and compact statements.

tsdata_mod = [[0 if (x < min_value or x > max_value) else x for x in y] for y in tsdata]

or in function mode:

def check(my_list):
    my_list_mod = [[0 if (x < min_value or x > max_value) else x for x in y] for y in tsdata]
    return my_list_mod

tsdata_mod = check(tsdata)

The above is in my opinion a very "pythonic" way to go about this task.


Also when looping through containers such as lists for example you don't do:

for i in range(len(tsdata)):
    for j in range(len(tsdata[i])):
        # do something with "tsdata[i]","tsdata[i][j]"

But rather:

for sublist in tsdata:
    for entry in sublist:
        # do something with "sublist", "entry"

And if you really need the indexes (which in your case you don't) you use the enumerate() function like so:

for i_sub, sublist in enumerate(tsdata):
    for i_entry, entry in enumerate(sublist):
        # do something with "i_sub", "sublist", "i_entry", "entry"
Ma0
  • 15,057
  • 4
  • 35
  • 65
  • Even simpler: `x if min_value <= x <= max_value else 0` – tobias_k Sep 02 '16 at 08:52
  • Thank you but I am actually trying to modify this list tsdata inside of a function, so this doesn't work. – othymomo Sep 02 '16 at 08:59
  • @OthmanNejjar What do you mean by that? Can you update the question? – Ma0 Sep 02 '16 at 09:00
  • your function does not return anything and of course you can use the list comprehension with the function. – Ma0 Sep 02 '16 at 09:08
  • What you are sugggesting is that it is better to return a new object rather than actually modify the list itself ? I was trying to do the latter – othymomo Sep 02 '16 at 09:12
  • @OthmanNejjar by changing the `tsdata_mod = check(tsdata)` to `tsdata = check(tsdata)` you have just one object – Ma0 Sep 02 '16 at 09:44
0

Your solution is not bad, but the following could be more simpler to understand. (depends of how your code should evolve later)

def new_value(value):
    """Encapsulation of the core treatment"""
    return 0 if (value < min_value) or (value > max_value) else value

new_tsdata = [[new_value(value) for value in row] for row in ts_data]

In python, you should seek for new objects instead of existing object modification.

aluriak
  • 5,559
  • 2
  • 26
  • 39
  • Why your last statement? True, this list comprehension is simpler that the nested loop needed for modifying the list, but is this a general truth? – tobias_k Sep 02 '16 at 08:54
  • Generally, i prefer list comprehension that are simpler to read. Her is a benchmark for [simple copy](http://stackoverflow.com/a/2612990/3077939). In case of modification of the object, i often see a performance gain. – aluriak Sep 02 '16 at 09:01
  • Thank you. I have edited the initial question. I am modifying a list argument inside a function so can't go for a new object... Or is this bad practice? – othymomo Sep 02 '16 at 09:08
  • As shown in [Ev. Kounis](http://stackoverflow.com/a/39288170/3077939) answer, it's always possible to copy instead of modify an object. This seems to me the better way to go, because your function has no side-effect, which is a very useful property. – aluriak Sep 02 '16 at 09:13
  • Ok, I'll go for that solution. Thank you ;) – othymomo Sep 02 '16 at 09:14