Nested Lists- Python - python

I need to write the body of a Python method that does the following:
1)takes a list, where list[0] is a string and list[1] is either a list which looks the same or None
2)print every string of the list
I have to use the while loop and not use list comprehension or flatten.
def pick_cherries_iter(field):
""""e.g.
>>> cherry_field = ['cherry1', ['cherry2', ['cherry3', ['cherry4', ['Yay!!!', None]]]]]
>>> pick_cherries_iter(cherry_field)
cherry1
cherry2
cherry3
cherry4
Yay!!!"""
_______________________
_______________________
_______________________
_______________________
while _________________:
_______________________
_______________________
_______________________
I know that for the example above I can print cheery1 if I print cherry_field[0] or cherry1 for cherry_field[1][0] or cherry2 for cherry_filed[1][1][0] etc, however I am not sure how to go through these elements using the while loop.

I think this should work for you. Please check it.
Using While Loop:
def pick_cherry(field):
""""e.g.
>>> cherry_field = ['cherry1', ['cherry2', ['cherry3', ['cherry4', ['Yay!!!',None]]]]]
>>> pick_cherry(cherry_field)
cherry1
cherry2
cherry3
cherry4
Yay!!!"""
while field[1] != None:
temp = field[0]
print temp
field = field[1]
print field[0]
Using Flatten(and Recursion):
flatten_field = []
def pick_cherry(field):
if field[1] != None:
flatten_field.append(field[0])
pick_cherry(field[1])
else:
flatten_field.append(field[0])
def flatten_func(field):
""""e.g.
>>> cherry_field = ['cherry1', ['cherry2', ['cherry3', ['cherry4', ['Yay!!!',None]]]]]
>>> flatten_func(cherry_field)
cherry1
cherry2
cherry3
cherry4
Yay!!!"""
pick_cherry(field)
for item in flatten_field:
print item

I would do this recursively because you have no way of knowing if an element is a list or not.
#!/usr/bin/python -E
cherry_field = ['cherry1', ['cherry2', ['cherry3', ['cherry4', ['Yay!!!', None]]]]]
def print_list(field):
i = 0
list_length = len(field)
while i < list_length:
if field[i] is not None and type(field[i]) is not list:
print(field[i])
else:
if field[i] is not None:
print_list(field[i])
i += 1
if i < list_length and type(field[i]) is list:
print_list(field[i])
i += 1
def pick_cherries(field):
if type(field) is list:
print_list(field)
pick_cherries(cherry_field)

Related

Enumerate list using recursion, python

I'm trying to enumerate the list using recursion and am having a hard time doing so.
If anyone can point me in the right direction that would be greatly appreciated! :)
def my_enumerate(items, start_index=0):
"""my enumerate"""
result = []
if not items:
return []
else:
a = (start_index, items[0])
result.append(a)
my_enumerate(items[1:], start_index + 1)
return result
ans = my_enumerate([10, 20, 30])
print(ans)**strong text**
Try:
def my_enumerate(items, start_index=0):
"""my enumerate"""
result = []
if not items:
return []
else:
a = (start_index, items[0])
result.append(a)
result += my_enumerate(items[1:], start_index + 1) # here
return result
The following is more concise:
def my_enumerate(items, start_index=0):
"""my enumerate"""
return [(start_index, items[0])] + my_enumerate(items[1:], start_index + 1) if items else []
As you are using recursion and you are declaring result = [] within a function so everytime it simply gets empty so you lose all previous results.
If you want exactly this to work there is also another way that by making the result as global if you wanted to use that list globally like below:
result = []
def my_enumerate(items, start_index=0):
"""my enumerate"""
global result
if not items:
return []
else:
a = (start_index, items[0])
result.append(a)
my_enumerate(items[1:], start_index + 1)
return result
ans = my_enumerate([10, 20, 30])
print(and)
But #CocompleteHippopotamus answer will work when you don't want to use a global keyword.

Converting a string to a nested dictionary

I have a string which I want to convert to a nested dictionary in Python.
Example Input :
import copy
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff.split("/")
final_temp_dict = dict()
for elem in reversed(diff_arr):
if len(final_temp_dict) == 0:
final_temp_dict.setdefault(elem, value)
else:
temp_final_dict = copy.deepcopy(final_temp_dict)
final_temp_dict.setdefault(elem, temp_final_dict)
print (final_temp_dict)
While running this I face an error and I'm not getting the expected output.
The output needed is as a nested dictionary:
{"pathConstraint" : {"latency" : {"latencyValue" : "low"}}}
You could use the following recursive function:
def string_to_dict(keys, value):
key = keys.split('/')
if len(key) == 2:
return {key[1]: value}
else:
return string_to_dict('/'.join(key[:-1]), {key[-1]: value})
Output:
>>> string_to_dict(diff_str, value)
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Note that this assumes that diff_str begins with a / character.
The following is an iterative approach. Note diff_arr[1:] is used to exclude the empty string that is generated from splitting on the initial /.
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff_str.split("/")
for key in list(reversed(diff_arr[1:])):
value = {key: value}
print(value)
Output
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
Shorter recursive approach:
def to_dict(d, v):
return v if not d else {d[0]:to_dict(d[1:], v)}
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
print(to_dict(list(filter(None, diff_str.split('/'))), value))
Output:
{'pathConstraint': {'latency': {'latencyValue': 'low'}}}
I tried to modify your function as little as possible, this should work just fine
import copy
def func():
diff_str = "/pathConstraint/latency/latencyValue"
value = "low"
diff_arr = diff_str.split("/")
final_temp_dict = dict()
for elem in reversed(diff_arr):
if elem == "":
continue
if len(final_temp_dict) == 0:
final_temp_dict[elem] = value
else:
temp_final_dict = copy.deepcopy(final_temp_dict)
final_temp_dict = {}
final_temp_dict[elem] = temp_final_dict
print (final_temp_dict)
However, there are much nicer ways to do something like this. See the other answers for inspiration.
def convert(items, value):
if not items:
return value
return {items.pop(0): convert(items, value)}
print(convert(diff_str.strip('/').split('/'), 'low'))

Referencing python variable inside functions

I have the following python code to delete all the copies of a file in a certain directory keeping only one of them.
It works fine if i comment out the first four lines in the delete() function but if i don't it gives me a error that local variable list1 referenced before assignment. Also I tried using something called global but it didn't help me much as it gave error saying that it is NoneType.
Please help me i am just a intermediate beginner in Python.
list1 = []
list2 = []
def stripe(lis):
for i in range(len(lis)):
lis[0] = lis[0].strip()
def scan(pat):
pat = os.path.abspath(pat)
files = os.listdir(pat)
for file in files:
filepath = os.path.join(pat,file)
if os.path.isfile(filepath):
list1.append(file)
list2.append('{0}'.format(filepath))
elif os.path.isdir(filepath):
scan(filepath)
def delete():
list1_1 = stripe(list1)
list2_1 = stripe(list2)
list1 = list1_1
list2 = list2_1
length = len(list1)
#length = length - 1
i = 0
while i < length:
item = list1[0]
a = list1[0]
b = list2[0]
del list1[0]
del list2[0]
if item in list1:
try:
os.remove(list2[list1.index(item)])
#del list1[list1.index(item)]
#del list2[list1.index(item)]
except:
print('sorry',list1[0],'could not be deleted',sep = ' ')
print('wow')
i += 1
#list1.append(a)
#list2.append(b)
global looks like the right option for you, but if you say it gives error, use the way that comes to mind first. list1 and list2 can be the parameters of the delete() function.
Something like this:
def delete(list1, list2):
...
def foo():
list1 = []
list2 = []
...
delete(list1, list2)
Also, as I said, global is always an option. Here is an easy example:
list = []
def foo():
global list
list.append(1234)
def foo2():
global list
print(list)
foo()
foo2()
Output:
[1234]

Sort a list with string and numbers

I need help to organize one list in python.
What I need is that:
I have a list like this: [10,50,20,'STRING',5], i need organize this list, without move the string, like this: [5,'STRING'10,20,50]. is possible do this?
Thanks!
I need to create a linked list to check if has intersection in two strings, i check this at 'def Intersecao', the output need to be Ordered, and if the intersection was empty, i need to print the string 'VAZIO'.
class No():
def __init__(self, valor = None, proximo = None):
self.valor = valor
self.proximo = proximo
def getValor(self):
return self.valor
def getProximo(self):
return self.proximo
def setProximo(self, novo_proximo):
self.proximo = novo_proximo
class lista():
def __init__(self, inicio = None):
self.inicio = inicio
def Inserir(self, valor):
novo_no = No(valor)
novo_no.setProximo(self.inicio)
self.inicio = novo_no
def Buscar(self, valor):
dados = self.inicio
while dados:
if dados.getValor() == valor:
return dados
else:
dados = dados.getProximo()
return None
def Intersecao (self, lista):
no = self.inicio
intersecao = []
while no != None:
if (not lista.Buscar(no.getValor())):
no = no.getProximo()
else:
if(no.getValor() == ''):
intersecao.append('VAZIO')
no = no.getProximo()
elif(no.getValor() in intersecao):
no = no.getProximo()
else:
intersecao.append(no.getValor())
no = no.getProximo()
return intersecao
def MostrarLista(self):
lista = []
dados = self.inicio
while dados:
lista.append(str(dados.getValor()))
dados = dados.getProximo()
print('->'.join(lista))
MyList = lista()
MySecondList = lista()
lista = []
lista2 = []
for i in range(40):
dado = input()
if i < 20:
lista.append(dado)
elif i >= 20:
lista2.append(dado)
for i in lista:
MyList.Inserir(i)
for i in lista2:
MySecondList.Inserir(i)
listaOrdenada = []
for elementos in sorted(MyList.Intersecao(MySecondList)):
print(elementos)
For first question, if it is list only, one way to do is (there might be better way though):
# original list
my_list = [10,50,20,'STRING',5]
# Creating temporary list with all numbers in sorted order and reverse
# reversed such that we use pop() which is efficient in time complexity
sorted_list = sorted([element for element in my_list if not isinstance(element, str)], reverse=True)
# new list to append accordingly
new_list = []
# for each element if it is string then in new list it has same position as in original list
# else if it was originally number then, we append the respective sorted number
for index, element in enumerate(my_list):
if isinstance(element, str):
new_list.append(element)
else:
new_list.append(sorted_list.pop())
new_list
Output:
[5, 10, 20, 'STRING', 50]
Or, it can be done with list comprehension which looks cleaner:
# Using list comprehension
my_list = [10,50,20,'STRING',5]
sorted_list = sorted([element for element in my_list if not isinstance(element, str)], reverse=True)
new_list = [element if isinstance(element, str) else sorted_list.pop() for index, element in enumerate(my_list)]
new_list
which gives same output.

Filtering a list of list in python

I have got a list of list like this
testList=[[1,'test',3],[4,'test',6],[1,6,7]]
My requirement is to create another list of list as follows
rstList=[[1,'test',3],[1,6,7]]
That is, list having element 'test' need to be appended only once to the rstList.
flag = True
for item in testList:
if ('test' in item and flag) or ('test' not in item):
flag = False
rtList.append(item)
testList=[[1,'test',3],[4,'test',6],[1,6,7]]
rstList = []
for item in testList:
matched = False
for result_item in rstList:
if item[1] == result_item[1]:
matched = True
if not matched:
rstList.append(item)
Assuming you only want to keep the the first sub-list with 'test' element, here's one approach:
def func(x):
global foundTest
if 'test' not in x: return True
elif not foundTest: foundTest = True; return True
return False
foundTest = False
rstList = filter(func, testList)
I hope following code would work for you
def genNewList(v):
test = False
ret = []
for el in v:
if ('test' in el):
if(test == False):
ret.append(el)
test = True
else:
ret.append(el)
return ret
testList=[[1,'test',3],[4,'test',6],[1,6,7]]
print 'Original list', testList
print 'New list', genNewList(testList)
Here you can run the script, and/or fork and play around with it.
filter(lambda x: x if 'test' in x else None, testList)

Categories

Resources