Repeat elememts based on another elements in the nested list - python

I have a nested list e.g., ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))].
And I would like to have the following modified list:
modified_ls=[((0,0),(0,0),(0,0),(1,0),(2,0),(2,0),(3,0)),((0,0),(1,0),(1,0),(1,0),(2,0),(2,0),(3,0))]
There the element (x,0) in modified_ls is repeated by N (N!=0) times which is based on the element (x, N) in ls.
Here is what I do (quite stupid):
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
modified_temp_ls=[]
for ii in ls:
for jj in ii:
temp=jj[1]
if temp==0:
modified_temp_ls.append(jj)
else:
while temp:
modified_temp_ls.append((jj[0],0))
temp-=1
ls2=modified_temp_ls[0:int(len(modified_temp_ls)/2)]
ls3=modified_temp_ls[int(len(modified_temp_ls)/2):int(len(modified_temp_ls))]
modified_ls=[]
modified_ls.append(tuple(ls2))
modified_ls.append(tuple(ls3))
Are there any simple way to do it (e.g, without using ls2 and ls3, etc.)? Thank you very much in advance for any suggestions!

This is just list manipulation. Generate the individual sequences, then use sum to combine them into a single list.
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
accum = []
for k in ls:
accum.append(sum([ [(i,0)]*max(1,n) for i,n in k ],[]))
print(accum)
Output:
[[(0, 0), (0, 0), (0, 0), (1, 0), (2, 0), (2, 0), (3, 0)], [(0, 0), (1, 0), (1, 0), (1, 0), (2, 0), (2, 0), (3, 0)]]
Or for the obligatory one liner:
ls=[((0,3),(1,0),(2,2),(3,0)),((0,0),(1,3),(2,2),(3,0))]
accum = [sum([[(i,0)]*max(1,n) for i,n in k ],[]) for k in ls]

Related

find path and convert from dictionary to list

I am using networkx library for Python with BFS and DFS. I need to get a tree and then explore it to get a path from a start node to an end node.
For the BFS part I am using bfs_successorsand it returns an iterator of successors in breadth-first-search from source.
For the DFS part I am using: dfs_successors and it returns a dictionary of successors in depth-first-search from source.
I need to get a list of nodes from source to end from both the algorithms. Each node is (x, y) and is a cell in a grid.
Here's what I've done so far:
BFS = nx.bfs_successors(mazePRIM, start)
print(dict(BFS))
DFS = nx.dfs_successors(mazePRIM, start)
print(DFS)
and I get this:
{(0, 0): [(0, 1), (1, 0)], (1, 0): [(1, 1)], (1, 1): [(1, 2)], (1, 2): [(0, 2), (1, 3)], (0, 2): [(0, 3)]}
{(0, 0): [(0, 1), (1, 0)], (1, 0): [(1, 1)], (1, 1): [(1, 2)], (1, 2): [(0, 2), (1, 3)], (0, 2): [(0, 3)]}
but I need an output like this:
[(0, 0), (1, 0), (1, 1), (1, 2), (1, 3)]
which is the list of nodes from start to end.
Do you have any advice about how to do it? Can you help me please?
Use a list comprehension and imply add .keys() to the end of your dictionaries:
DFS = nx.bfs_successors(mazePRIM,start)
print([n for n in dict(BFS).keys()])
DFS = nx.dfs_successors(mazePRIM, start)
print([n for n in DFS.keys()])
You can read more about dictionary keys here:
How to return dictionary keys as a list in Python?
You can simply convert the dictionary keys directly to a list:
DFS = nx.bfs_successors(mazePRIM,start)
print(list(dict(BFS).keys()))
DFS = nx.dfs_successors(mazePRIM, start)
print(list(dict(DFS).keys()))

Order of For Loops with Python List Comprehension

In this answer, it is claimed that
The best way to remember this is that the order of for loop inside the list comprehension is based on the order in which they appear in traditional loop approach. Outer most loop comes first, and then the inner loops subsequently.
However, this answer,, and my own experiment below, seem to show the opposite - i.e, the inner loop coming first.
In my example, I want j to represent the row number and i to represent the column number. I want 5 rows and 4 columns What am I missing please?
board = [[(j, i) for i in range(4)] for j in range(5)]
# I believe the above comprehension is equivalent to the nested for loops below
# board = []
# for j in range(5):
# new_row = []
# for i in range(4):
# new_row.append((j,i))
# board.append(new_row)
for j in range(5):
for i in range(4):
print(board[j][i], end="")
print()
This is the correct way to get desired output:
board = [(j, i) for i in range(4) for j in range(5)]
Output:-
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (0, 3), (1, 3), (2, 3), (3, 3), (4, 3)]

How to put the tuple (i,j) in a list multiple times without using concatenation?

I want to add some tuples (i,j) in a list as many time as they occur in another function. My result right now is [[(0, 0), (0, 0)]], but I want it to be only a single list [(0, 0), (0, 0)]. Is there any way I can do this without using libraries?
list= [[(i,j)]*number_occurences]
print(list)
>>> [[(0, 0), (0, 0)]]
You literally wrote the [[ that you don't want. So, simply don't do that! Write just the one [ instead.
For example:
>>> [(1,2)]*5
[(1, 2), (1, 2), (1, 2), (1, 2), (1, 2)]

For loop to compare one element with all the remaining elements of an array

I have an array in Python [0,1,2,3,4] with 5 elements. I want to compare elements in following fashion.
(0,1),(0,2),(0,3),(0,4),(1,2),(1,3),(1,4),(2,3),(2,4),(3,4),(4,4)
What I am doing is as follows.
for i in range(len(array)):
for j in range(i+1,len(array)):
But this is comparing in following fashion.
(0,1),(1,2),(2,3),(3,4)...
Where I am doing it wrong?
This code produces the desired result:
array = [0,1,2,3,4]
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
print(array[-1], array[-1])
This code is one way that you may have gotten the erroneous result:
for i in range(len(array)):
for j in range(i+1,len(array)):
print(array[i], array[j])
break
Using itertools is another option:
>>> [x for x in itertools.combinations(xrange(5), 2)]
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]

Python: Remove a Sublist Which Contains Only One Instance of an Item

everyone! Basically, I need to remove every sublist from a list which contains only one of any item - so long as that item itself is not one.
Here's an example: If I had this,
list = [(0, 0), (0, 1), (0, 2), (1, 1), (1, 0), (1, 3), (2, 0), (0, 3)]
I would in turn want this:
list = [(0, 0), (1, 1)]
What I originally tried was:
for sublist in list:
for item in sublist:
if sublist.count(item) == 1 and item != 1:
list.remove(sublist)
Unfortunately, this interfered with the cycling of the original for-loop (I think), so I would end up with things like: ValueError: list.remove(x): x not in list Any help appreciated.
EDIT: I'd like to apologize, (1, 3) should not be in the output! Sorry for the confusion, hopefully this program will be better at doing this than I am!
Copy the list before running the for loop, so the iterable don't get modified during the loop
Remove one sublist once and break, don't try to remove it twice.
Though I'm only getting [(0, 0), (1, 1)] but not (1,3) in output.
for sublist in list[:]:
for item in sublist:
if sublist.count(item) == 1 and item != 1:
list.remove(sublist)
break
I'm not sure I understand the task but changing list while iterating it is never a good idea.
try to copy it first and then iterate over the copy.
something like:
list_copy = list[:]
for sublist in list_copy:
for item in sublist:
if sublist.count(item) == 1 and item != 1:
list.remove(sublist)
note that list_copy = list will copy the reference which means changing one list will change the other as well so you want to write list_copy = list[:]
P.S.
using the list type name as a variable is a very bad idea. try to use a different name.
I must say your explanation of what the code does isn't clear.
You might want to move to while loops:
List = [(0, 0), (0, 1), (0, 2), (1, 1), (1, 0), (1, 3), (2, 0), (0, 3)]
i = 0;
o = 0;
while i<len(List):
while o<len(List[i]):
if List[i].count(o) == 1 and List[i][o] != 1:
List.remove(List[i])
o+=1
i+=1
o=0;
print(List)
I got:
[(0, 0), (0, 2), (1, 1), (1, 3), (0, 3)]
You can use the filter function to filter a list. First, write a function that takes an element of your list and returns True if the element should be in the list, and False if not. Like this:
def predicate(x):
for item in x:
if x.count(item) == 1 and item != 1:
return False
return True
Now, you can take your list (Don't call it list, since list is a function we will have to use in a second, and by calling something list you can't use said function)
l = [(0, 0), (0, 1), (0, 2), (1, 1), (1, 0), (1, 3), (2, 0), (0, 3)]
And filter it with the predicate:
itr_res = filter(predicate,l)
Note, however that this returns an iterable, and not a list. You probably want a list, so use the list function to construct one from the iterable.
res = list(itr_res)
this gives the resulting list:
[(0,0),(1,1)]
As others have noted, it is hard to figure out exactly what you want your function to filter. Your code does one thing, your example and other and your description is vague. You can try to play around with the predicate function until you get it to do what you actually want
I think that this code is right for you:
list = [(0, 0), (0, 1), (0, 2), (1, 1), (1, 0), (1, 3), (2, 0), (0, 3)]
out_list = [t for t in list if (t[0] == t[1]) or t.count(1) > 0]
This code generates a new list and then you can reassign it to your input list.
But the code above generates on your input:
[(0, 0), (0, 1), (1, 1), (1, 0), (1, 3)]
Sorry, if I understand your task incorrectly.

Categories

Resources