Finding and replacing within a 'grouped' list - python

Is there a way to do a find and replace for lists that are sorted into groups?
Scenario:
my_list = [[1,5],[3,6],[-1,9]]
I want to replace all the values that are 1 or 3 to be replaced with 11 such that output is:
my_list = [[11,5],[11,6],[-1,9]]
I have been able to do the find replace by creating 3 variables and adding it such that it is one big list however I still want to retain the same form thus I am wondering how to do it while it's still in that form?

The alternative to the list comprehension solution would be modifying the original list with:
for group in my_list:
for i, x in enumerate(group):
if x in {1, 3}:
group[i] = 11
This would be the best option if your lists contain a large number of elements.

You could achieve this with a nested list comprehension such as:
my_list = [[y if y not in [1, 3] else 11 for y in x] for x in my_list]
This retains the nested list structure and replaces any 1 or 3 with 11. Output is:
[[11, 5], [11, 6], [-1, 9]]

Related

Basic question about replacing entries in list of lists according to if condition

How can I change this code so the I replace the elements for a different if condition?
In the code below I change replace the 3 with 5.
But what if the wanted to replace the entry to 5 if any sub-list entry is larger than 30?
Example: If L[i][j] > 30 I get [[3,3],[5,5],[5,1], [5,8]]
L = [[3,3],[444,1111],[45,1], [90,8]]
for i, x in enumerate(L):
for j, a in enumerate(x):
if 3 in a:
L[i][j] = a.replace(3, 5)
****** Disclaimer *******:
The example was taken from this enclosed question for the sake of convenience. My aim in this question is to understand how to use the indexes so it fits a different type of if condition.
Replace elements in a list of lists python
Quick and dirty answer:
L = [[3,3],[444,1111],[45,1], [90,8]]
L = [[5 if value < 30 else 5 for value in list ] for list in L]
print(L)
out:
[[3, 3], [5, 5], [5, 1], [5, 8]]
Better way using a function
If you want to replace the values then it's better to create a simple function as shown below. You seem to have copied the code from somewhere else, so I will try my best to explain to you what is going on below.
Our original list is shown below:
L = [[3,3],[444,1111],[45,1], [90,8]]
The function below is defined to accept 3 values, the first value is the list to be manipulated, the second is the condition, as in replace if number is > condition. The third value is the new value to replace the values that satisfy the condition.
def replace_greater_than(List,condition = 30,new_value = 5):
L = [[value if value < condition else new_value for value in list ] for list in List]
Here we are using a concept know as nested list comprehension. Start by reading it from right to left. We are looping through every list in List (notice the case), please note that "list" in the code can be replaced with any variable name that you want, but i just called it "list" to improve readability.
So now we are looping through our initial list and we are retrieving the inner lists with each iteration.Then we perform list comprehension again on the inner lists that we just retrieved, so now we are looping on the values in the list themselves.
Finally in the inner list comprehension we set a condition, which is passed on by the user, if the value is less than the set condition or threshold then return the same value else return the specified new value.
How to use the function:
Example: here we place the condition as 30 and the value as 5
replace_greater_than(List = L, condition = 30, value = 5)
out:
[[3, 3], [5, 5], [5, 1], [5, 8]]
Example: We can also call the function without passing any values to the parameters because we already set the default values of our function earlier; condition = 30, new_value = 5.
replace_greater_than(List = L)
out:
[[3, 3], [5, 5], [5, 1], [5, 8]]
Example: Finally, we can also pass custom values to our function. The function below will replace all the values greater than 100 with the new_value of 23
replace_greater_than(List = L, condition = 100, new_value = 23)
out:
[[3, 3], [23, 23], [45, 1], [90, 8]]
Here are some sources to help you get started with learning python:
Great free Course covering all the basics by Microsoft
List Comprehension
Functions in python
Some channels on Youtube that I recommend:
Real Python
Corey Schafer
DataCamp
Basically you have a loop through all elements, then you have condition and action when condition is met.
for i, x in enumerate(L): #loop
for j, a in enumerate(x): #loop
if 3 in a: #condition
L[i][j] = a.replace(3, 5) #action
You want to change condition to if L[i][j] > 30 (already in your question), and you want to change action to replace or reassign entry, which is straightforward L[i][j] = 5.
In above code a is L[i][j], so you can write condition a bit differently.
I will let you modify code yourself and test. You don't need to use list comprehension at this point.
Thea easy way to do it is to iterate over each item in each list and change items via an 'if' statement.
Create a statement which will return either the item it is given, or 3 if the number is equal to 5.
replace = lambda i: 3 if i==5 else i
Next, iterate through the nested lists. This can be written out in two ways, via list comprehension or as nested for statements.
l = [[replace(l2)for l2 in l1] for l1 in l]
for l1 in l:
for l2 in l1:
l2 = replace(l2)
When we run the code we get:
print (l)
>>> [[3, 3], [444, 1111], [45, 1], [90, 8]]
To make the code change any items <30 we can change the if statement we made at the start.
replace = lambda i: 3 if i<30 else i
Printing the new code gives:
print (l)
>>> [[3, 3], [444, 1111], [45, 3], [90, 3]]
Note, using x.replace() works for strings not integers, you can play with int() and str() if you need to use .replace().

Get one resulting list with the max or min by index in a nested list

Lets say I have this structure
[[[1,2],[3,4]],[[8,9],[7,7]]]
I want to iterate the list and have this result:
[[3,2],[8,7]]
This is would be reducing the list list of arrays in the first level [[1,2],[3,4]] to one single array where the maximum selected for the first element and the minimum is found for the second.
I have already done it manually, just iterating the groups, iterating again, storing the first value and seeing if the next is bigger or smaller, I store it in a list and create another list.
I would like to find a more elegant method with list comprehensions and so on, I'm pretty sure I can use zip here to group the values in the same group but I haven't been successful so far.
You can use zip, and by unpacking the result into individual values it is pretty easy to do what you are looking for, e.g.:
>>> x = [[[1,2],[3,4]],[[8,9],[7,7]]]
>>> [[max(a), min(b)] for k in x for a, b in [zip(*k)]]
[[3, 2], [8, 7]]
An alternative way without unpacking is to have a cycling function iterable (max, min, max, min, ...) and use nested list comprehensions, e.g.:
>>> import itertools as it
>>> maxmin = it.cycle([max, min])
>>> [[next(maxmin)(a) for a in zip(*k)] for k in x]
[[3, 2], [8, 7]]
Or index into a list of functions:
>>> import itertools as it
>>> maxmin = [max, min]
>>> [[maxmin[i](a) for i, a in enumerate(zip(*k))] for k in x]
[[3, 2], [8, 7]]
This will work without zip:
mylist = [[[1,2],[3,4]],[[8,9],[7,7]]]
[[max(y[0] for y in x), min(y[1] for y in x)] for x in mylist]
The main disadvantage of this is that it looks through each sub-list twice, once to find the maximum (of the first items) and once to find the minimum (of the second items).

Using List Comprehensions to create multiple SubList in a list

I have a list:
list1 = [0,2,4,6]
Here I want to add number 2 to the list1 and create a sublist in new list , and create another sublist using the first sublist to create new sublist .
I want to create a new list from list1 with the help of list comprehentions only and that too in single line .
newList = [[2,4,6,8],[4,6,8,10],[6,8,10,12]]
For example :
newList = [a+2 for a in list1]
but with this code I am able to create only 1 list inside newList.but I want to create 3 sublist accordingly in newList using list Comprehensions only.
Given
list1 = [0,2,5,6]
you can create 3 lists inside a list using 2 nested list comprehensions:
newlist = [[x+2*(i+1) for x in list1] for i in range(3)]
the result
[[2, 4, 7, 8], [4, 6, 9, 10], [6, 8, 11, 12]]
is different from the one in the question, but Jim edited it in the meanwhile (for correctness), and I personally prefer that the input list has no internal logic (else we could be tempted to only use range to solve that).
Note that we can do it with list comprehension only because we can deduce the sublists from the initial input list. It's not possible in general to compute current element from previous one using list comprehension. You have to switch to a "classical" for loop in that case.

How to pick the smallest value in a list when an iterative process is applied to the list

I need to find the smallest value in a series of lists. I understand the code for the smallest value in just one list:
>>> x = [1, 2, 3, 4, 5]
>>> print (min(x))
1
Simple enough. However, I would like to know if there is a way to write code that finds the smallest value for each list I have without stopping and adjusting the code (whether by an iterative process or some other means). Any help would be greatly appreciated. Thanks in advance!
First, make a list of lists out of your separate lists. For example, if you have lists A, B and C, the list of lists would be [A,B,C].
Now, to get a list of all the minimum values for each list in a list of lists lst:
[min(x) for x in lst]
To get the global minimum:
min(x for sublist in lst for x in sublist)
Demo:
>>> lst
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [min(x) for x in lst]
[1, 4, 7]
>>> min(x for sublist in lst for x in sublist)
1
Edit in reaction to OP's comment:
I just want the minimum value for each list. I don't need to compile all of the minimum values together into a new list
If you just want to print the minimum values for each list A, B, C, ... , you can do:
for lst in (A,B,C): # put as many lists as you like into the parentheses
print(min(lst))
Edit in reaction to
I am only accessing one list (in this case, the values are well depths) at a time. [..] What I would like to know is how to write a code that finds the smallest value in a list given that the iterator essentially changes the values in said list.
Just print(min(lst)) each time lst has changed.
Assuming you've got a list of lists, this should do it:
minimums = [min(l) for l in lists]

Concatenate List Object Name with a Number and Retain the List Python

I'm using python 2.7 I'm trying to figure out a way to change the names of my lists automatically.
Let me explain i have multiple lists
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 9, 3]
list3 = [8, 4, 3, 2, 1]
I would like to call the lists in a loop to determine which lists contain or do not contain a particular number.
My first thought was
x = "list" + str(i) # (where i iterates in the loop)
print x
However, using the above code only gave me the string "list1"(when i=1).
What I want is to be able to call the list that is named list1 and use the .count() operator to determine whether or not the number exists if it doesn't i want to call the next list until I'm out of lists(there will eventually be up to 30 lists).
Thanks,
Ryan
You shouldn't approach it like this. Put your lists in a container to iterate over them instead:
In [5]: for l in (list1, list2, list3):
...: print l.count(2)
...:
1
0
1
What you could do in a real-life use case is create a list of lists and fill it dynamically.
Then to get the first list that contains a given number, you could do:
In [6]: lists = [list1, list2, list3]
In [7]: next(l for l in lists if 9 in l)
Out[7]: [4, 5, 9, 3]
put the list in dict:
list1 = [1,2.4]
list2 = [2,5,6]
dlist = {1:list1,2:list2}
for k in dlist:
print dlist[k]

Categories