while loop with dynamic list in python using a dictionnary - python-3.x

I have a dictionary with lots of data from a CSV file where the key is the row number and the value is a list that contains the column data.
What I want to do is to check from a data of each line (key) and from column 2, I take its data from column 4 and then look for this data in column 2 of another line (key) and take its data in column 4 and continue until it finds the last value of column 4 in column 2.
My code is this:
dict_FH_coord = self.dict_FH()
site_SI='some_site'
list_test = [site_SI]
while len(list_test) > 0:
for ele in list_test:
for cle, val in dict_FH_coord.items():
list_test = []
if val[2] == ele:
list_test.append(val[4])
list_def.append(val)
print(val)
But this code does not work because it stops at the first iteration and it finds that the elements linked to the starting site_SI only
Is there a way to do successive iterations with the list list_test which becomes dynamic to solve my problem?

If you want to modify list 'on air' you sohuld do something like
a = [1, 2, 3]
a[:] = [1, 2]
In your case the only way you may use this inside the loop (avoiding infinite list size increasement):
if val[2] == ele:
list_test[:] = list_test[1:]+[val[4]]
list_def.append(val)
else:
list_test[:] = list_test[1:]
But it wont work as intended because previous iteration ends at index 1 (for ele in list_test:), and list_test would never change in size.
Both this cases can not be merged with each other.
I suggest you to use Queue, but be careful to avoid infinite links looping inside your data:
from queue import Queue
dict_FH_coord = {
1: [0, 1, 'some_site', 3, 'some_site_2'],
2: [0, 1, 'some_site_2', 3, 'some_site_3'],
3: [0, 1, 'some_site_2', 3, 'some_site_4'],
4: [0, 1, 'some_site_3', 3, 'some_site_5'],
}
site_SI = 'some_site'
unvisited = Queue()
unvisited.put(site_SI)
list_def = list()
while not unvisited.empty():
ele = unvisited.get()
for cle, val in dict_FH_coord.items():
if val[2] == ele:
unvisited.put(val[4])
list_def.append(val)
print(val)

Related

How to get duplicates in sorted list with O(n) python

Hear i have a list, and i have to get duplicates from it. So i can use solution like this:
arr = [1, 1, 2, 3, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*duplicates)
Ok, what if i have three or more duplicates in my list? I did something like that:
arr = [1, 1, 1, 2, 3, 4, 4, 4, 4, 5]
def get_duplicates(arr):
duplicates = []
for index in range(len(arr)-1):
if arr[index] == arr[index+1]:
duplicates.append(arr[index])
return duplicates
print(*set(duplicates))
Is that both my code works with O(n) or not? I just dont know what is speed of set() function in python, but i think that first for loop takes O(n),
if set() takes O(n), it doesnt matter, because finally i will have O(2n) = O(n) in this case.
Do i solve that task correctly, or my code is not effective? Smart people, help me please))
If u know how to do it in wright direction, explain me please.
Here is a version that is clearly O(n):
def get_duplicates(arr):
last_duplicate = None
duplicates = []
for i,v in enumerate(arr[1:]):
if v==arr[i-1] and v!=last_duplicate:
duplicates.append(v)
last_duplicate = v
return duplicates
Note that this assumes, as your original code does, that duplicates will be adjacent to one another. It also assumes that the first duplicate is not None.

Looping through an iterable data structure in python whose value changes every iteration

My code looks like this :
input_list = [0,3,5,7,15]
def sample_fun(input_list):
for idx,ele in enumerate(input_list):
input_list = [x-2 for x in input_list if (x-2)>0]
print('Index:',idx,'element:',ele,'New list:',input_list)
sample_fun(input_list)
What I am trying to show is that the value of input_list that is used inside of enumerate keeps changing inside the for loop. I want the for loop to iterate through the new value of input_list. But it appears that the for loop iterates through the initial value of input_list even though I am changing it's values.
Index: 0 element: 0 New list: [1, 3, 5, 13]
Index: 1 element: 3 New list: [1, 3, 11]
Index: 2 element: 5 New list: [1, 9]
Index: 3 element: 7 New list: [7]
Index: 4 element: 15 New list: [5]
I understand that the for loop is iterating through the initial enumerate output.
Is there any way I could make the for loop iterate through the new values of input_list like:
In the first iteration when index: 0 and element:0, input_list = [1, 3, 8, 13]
In the next iteration, I want the values to be like this - index: 0 and element: 1 and input_list = [1, 3, 11]
In the next iteration, I want the values to be like this - index: 0 and element: 1, now since the element is same as previous element value, I would like to loop through to - index:1 and element : 3 and input_list = [1, 9]
I want the loop to behave in this way.
I want to loop through the changing values of the input_list.
I'm not sure how to do this. It would be great if anybody could help me out here. Thanks in advance!
In the for loop, you keep assigning to input_list a new list object:
input_list = [x-2 for x in input_list if (x-2)>0]
while the iterator of the for loop is based on the original list object, and it therefore would not reflect the new list objects assigned to input_list.
You can instead alter input_list in-place by slicing its entire range:
input_list[:] = [x-2 for x in input_list if (x-2)>0]
so that the iterator can reflect changes made to the same list object.

How can I count the number of times a specific number appears in list vertically in python 3?

I'm trying to count the number of times a specific number appears in serval lists vertically.
My code:
import csv
with open('Superheroes.csv', 'r') as csvfile:
first_line = csvfile.readline()
super_reader = csv.reader(csvfile, delimiter=',')
result = []
for vote in super_reader:
vote.pop(0)
result.append([int(x) if x else 0 for x in vote])
result = [vote.count(1) for i in zip(*result)]
print(result)
example picture
So from the example picture, say I wanted to know how many times the number 11 appeared in every column of all the lists. I would expect an output of [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 4, 2]
Thanks
You can use sum with a generator expression that outputs whether each item in a column matches the target number to perform the counting after transposing the rows into columns with zip:
def count(rows, num):
return [sum(i == num for i in map(int, col)) for col in zip(*rows)]
so that given the content of test.csv as follows:
2,1,3
3,2,1
1,3,3
1,3,2
count(csv.reader(open('test.csv')), 3) would return:
[1, 2, 2]
Demo: https://repl.it/#blhsing/IllAffectionateQuarks#main.py

finding the keys of all the largest values in python dictionary?

if I have a dictionary
x ={0: 0, 1: 4, 2: 0, 3: 2, 4: 2, 5: 4}
how do i get the keys of all the largest values
In this case they would be 1 and 5 .
Not a duplicate question. looking to find all the keys and not just the one.
x ={0: 0, 1: 4, 2: 0, 3: 2, 4: 2, 5: 4}
maximum = max(x.values())
keys = [key for key, value in x.items() if value == maximum]
print(keys) # => [1, 5]
There is a class in collections called Counter that does exactly what you want. It provides the exact functionality you require via it's most_common method:
from collections import counter
maxes = Counter(x).most_common(2)
print([x[0] for x in maxes])
[1, 5]
Now this is probably not exactly what you want because I hard coded in the number 2. You can get this by using another Counter on the values of your dictionary!
x = Counter(x) # This preserves x: just makes it a subclass of dict
max_count = Counter(x.values())[x.most_common(1)[0][1]]
maxes = x.most_common(max_count)
maxes = [x[0] for x in maxes]
Here, I compute the number of times that the most common value occurs by counting all the different values, and then checking the maximum one using x.most_common(1)[0][1].
Please do not select this answer. #BrightOne has the right answer. This is just a thing I did to see if I could avoid using anything but Counters. It is not actually a good idea.

how to find the empty spot in a row?

I am suppose to put a group of people (given at run-time) in to a 2 dimensional array of spot, group together in a row randomly(find out all possible positions and randomly pick one)
To start of, I wanna try in an array first
if I have an array of spots of size 10 like below
spots[occupied,open,open,occupied,occupied,occupied,open,open,open,open]
to put 2 people
Is there a particular algorithm to do this kind of problem?
Thanks for any help!
in python:
seats =["occupied","open","open","occupied","occupied","occupied","open","open","open","open"]
def empty(seats,index,count):
if count == 0:
return True
else:
return (seats[index] == "open") & empty(seats,index+1,count-1)
def findEmpty(seats,count):
result = []
for (i=0;i<seats.size-count+1,i++)
if empty(seats,i,count):
result.append(<list of consecutive numbers from i to i+count>)
return result
print findEmpty(seats,2)
>>>[[1, 2], [6, 7], [7, 8], [8, 9]]
here's another approach, its a little more efficient:
seats = ["occupied","open","open","occupied","occupied","occupied","open","open","open","open"]
//counts the number of consecutive free seats starting at position index
def countEmpty(seats,index):
if index >= len(seats) or seats[index] == "occupied":
return 0
return 1 + countEmpty(seats,index+1)
def findEmpty(seats,count):
result = []
i = 0
while i < len(seats)-count+1:
c = countEmpty(seats,i)
if c>=count:
for (j=i;j<i+c-count+1;j++):
result.append(<list of consecutive numbers from j to j+count>)
i += 1 + c
return result
print findEmpty(seats,2)
>>>[[1, 2], [6, 7], [7, 8], [8, 9]]
and finally, if you did choose to use python you could do it in one line:
seats =["occupied","open","open","occupied","occupied","occupied","open","open","open","open"]
count = 2
print [range(i,i+count) for i in range(len(seats)-count+1) if all([seats[j]=="open" for j in range(i,i+count)]) ]
>>> [[1, 2], [6, 7], [7, 8], [8, 9]]
Pseudo code:
//Create 2 lists of blocks, both empty: tmp and final
List tmp=new List;
List final=new List;
//Cycle the seats
for (int i=0;i<length(seats);i++) {
//If the seat is occupied, start over
if (seats[i]==occupied) tmp.empty();
else {
//Cycle existing block candidates, add free seat
foreach (ref block in tmp) {
block.add(seats[i])
if (length(block)>=people_count) {
//HEUREKA, got a fitting block: Move it to the final list
tmp.remove(block)
final.add(block)
}
}
//Start a new block with this seat
tmp.add(new block(seats[i]));
//Read below for this edge case
}
}
final now has the blocks.
If you allow the edge case of people_num being 1, you have to check for a complete block at the position indicated in the pseudocode
I shall use Mathematica code but I believe you can follow the logic.
Starting with:
dat = spots[occupied, open, open, occupied, occupied, occupied, open, open, open, open];
fill = {"Alpha", "Bravo", "Charlie", "Delta", "Echo", "Foxtrot"};
First find a random permutation of the list fill (it is easy to find an algorithm on StackOverflow):
randomfill = RandomSample # fill
{"Delta", "Echo", "Alpha", "Bravo", "Charlie", "Foxtrot"}
Then "map" a function onto each element of the spots list, and if the element is open return the next value from the randomfill list, else return the element unchanged:
i = 1;
If[# === open, randomfill[[i++]], #] & /# dat
spots[occupied, "Delta", "Echo", occupied, occupied, occupied, "Alpha", "Bravo", "Charlie", "Foxtrot"]

Resources