I need to run through db using recursion and get a list of results at the end. Function works correct (if print unrem) but I cann't return the list of results.
def find_locks(item, ids):
if item.video_id:
#print (item.video_id, ids)
return (item.video_id, ids)
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
find_locks(i, ids.append(i.id))
else:
find_locks(i, ids)
How can I get the list results?
I'd use a recursive generator instead of building a list:
def find_locks(item, ids):
if item.video_id:
yield (item.video_id, ids)
for i in CatalogItem.objects.filter(parent=item):
nxt = ids + [i.id] if i.is_lock else ids
for x in find_locks(i, nxt):
yield x
In python 3.3 you can use yield from for the last part.
Try something like the following:
def find_locks(item, ids):
if item.video_id:
return [(item.video_id, ids)]
res = []
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
res.extend(find_locks(i, ids + [i.id]))
else:
res.extend(find_locks(i, ids))
return res
In the base case you return list with the only one item included. If it's not the base case, you make a new list, execute recursive call, extend the list with result of recursive call and return this list.
You can simply store each result in a list and return that at the end:
def find_locks(item, ids):
if item.video_id:
return [(item.video_id, ids)]
result = []
for i in CatalogItem.objects.filter(parent=item):
if i.is_lock:
result.extend(find_locks(i, ids + [i.id]))
else:
result.extend(find_locks(i, ids))
return result
Note that you need to return each item in a list as well because other calls to find_locks expect to receive a list as return value.
Related
So I wrote this code to return back every string in the given lst: list once. Here is my code
def make_unique(lst: list[str]):
s = []
for x in lst:
if lst.count(x) == 1:
s.append(x)
else:
return(x)
return s
When I put in the input:
print(make_unique(lst=['row','mun','row']))
The output returns
row
but I want my output to return
['row','mun']
which is basically all the strings in the list printed once.
How can I do this??
Why not you try this one line short code to remove duplicates from your list and make it unique
def make_unique(lst):
return list(dict.fromkeys(lst))
print(make_unique(['row','mun','row'])) #['row','mun']
Easy way to do this is turn the list into a set. A set only shows each item once and thats what you want.
lst=['row','mun','row']
setLst = set(lst)
for elem in setLst:
print(elem)
You can use set.
lst=['row','mun','row']
print(set(lst))
I have a data set as a list. From that list I need to find a keyword, and if found, I should be able to extract the complete information of that element.
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
from the above list, if I search only CountryCode, then the output should come as:
['CountryCode/US','CountryCode/UK']
Below is my code which I am trying, but it is returning only a single value.
Can some one help me with this code, to return all of the values as :
['CountryCode/US','CountryCode/UK']
def att_func(field,data):
for i, j in enumerate(data):
# print(i,j)
if field in j:
return [data[i]]
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
field ='CountryCode'
Cntry = att_func('CountryCode',att)
print(Cntry)
You're returning early in your for loop so you'll never get past the first position where the field exists, you can either use yield instead of return and make your function return a generator or just use a list comprehension
def att_func(field, data):
return [i for i in data if field in i]
Reason : This is because you are returning as soon as single data is getting.
Solution : Collect all data in list and the return collected data.
Try:
def att_func(field,data):
final_data = []
for i, j in enumerate(data):
# print(i,j)
if field in j:
final_data.append(data[i])
return final_data
att =['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
field ='CountryCode'
Cntry = att_func('CountryCode',att)
print(Cntry)
att = ['Email/xyz#gmail.com', 'CountryCode/US','CountryCode/UK', 'ID/12345']
out = [item for item in att if "CountryCode" in item]
Done !
Your att_func should look like this:
def att_func(needle, haystack):
return [item for item in haystack if needle in item]
More on list comprehensions.
Given a basic class Item:
class Item(object):
def __init__(self, val):
self.val = val
a list of objects of this class (the number of items can be much larger):
items = [ Item(0), Item(11), Item(25), Item(16), Item(31) ]
and a function compute that process and return a value.
How to find two items of this list for which the function compute return the same value when using the attribute val? If nothing is found, an exception should be raised. If there are more than two items that match, simple return any two of them.
For example, let's define compute:
def compute( x ):
return x % 10
The excepted pair would be: (Item(11), Item(31)).
You can check the length of the set of resulting values:
class Item(object):
def __init__(self, val):
self.val = val
def __repr__(self):
return f'Item({self.val})'
def compute(x):
return x%10
items = [ Item(0), Item(11), Item(25), Item(16), Item(31)]
c = list(map(lambda x:compute(x.val), items))
if len(set(c)) == len(c): #no two or more equal values exist in the list
raise Exception("All elements have unique computational results")
To find values with similar computational results, a dictionary can be used:
from collections import Counter
new_d = {i:compute(i.val) for i in items}
d = Counter(new_d.values())
multiple = [a for a, b in new_d.items() if d[b] > 1]
Output:
[Item(11), Item(31)]
A slightly more efficient way to find if multiple objects of the same computational value exist is to use any, requiring a single pass over the Counter object, whereas using a set with len requires several iterations:
if all(b == 1 for b in d.values()):
raise Exception("All elements have unique computational results")
Assuming the values returned by compute are hashable (e.g., float values), you can use a dict to store results.
And you don't need to do anything fancy, like a multidict storing all items that produce a result. As soon as you see a duplicate, you're done. Besides being simpler, this also means we short-circuit the search as soon as we find a match, without even calling compute on the rest of the elements.
def find_pair(items, compute):
results = {}
for item in items:
result = compute(item.val)
if result in results:
return results[result], item
results[result] = item
raise ValueError('No pair of items')
A dictionary val_to_it that contains Items keyed by computed val can be used:
val_to_it = {}
for it in items:
computed_val = compute(it.val)
# Check if an Item in val_to_it has the same computed val
dict_it = val_to_it.get(computed_val)
if dict_it is None:
# If not, add it to val_to_it so it can be referred to
val_to_it[computed_val] = it
else:
# We found the two elements!
res = [dict_it, it]
break
else:
raise Exception( "Can't find two items" )
The for block can be rewrite to handle n number of elements:
for it in items:
computed_val = compute(it.val)
dict_lit = val_to_it.get(computed_val)
if dict_lit is None:
val_to_it[computed_val] = [it]
else:
dict_lit.append(it)
# Check if we have the expected number of elements
if len(dict_lit) == n:
# Found n elements!
res = dict_lit
break
I'm attempting to generate all n choose k combinations of a list (not checking for uniqueness) recursively by following the strategy of either include or not include an element for each recursive call. I can definitely print out the combinations but I for the life of me cannot figure out how to return the correct list in Python. Here are some attempts below:
class getCombinationsClass:
def __init__(self,array,k):
#initialize empty array
self.new_array = []
for i in xrange(k):
self.new_array.append(0)
self.final = []
self.combinationUtil(array,0,self.new_array,0,k)
def combinationUtil(self,array,array_index,current_combo, current_combo_index,k):
if current_combo_index == k:
self.final.append(current_combo)
return
if array_index >= len(array):
return
current_combo[current_combo_index] = array[array_index]
#if current item included
self.combinationUtil(array,array_index+1,current_combo,current_combo_index+1,k)
#if current item not included
self.combinationUtil(array,array_index+1,current_combo,current_combo_index,k)
In the above example I tried to append the result to an external list which didn't seem to work. I also tried implementing this by recursively constructing a list which is finally returned:
def getCombinations(array,k):
#initialize empty array
new_array = []
for i in xrange(k):
new_array.append(0)
return getCombinationsUtil(array,0,new_array,0,k)
def getCombinationsUtil(array,array_index,current_combo, current_combo_index,k):
if current_combo_index == k:
return [current_combo]
if array_index >= len(array):
return []
current_combo[current_combo_index] = array[array_index]
#if current item included & not included
return getCombinationsUtil(array,array_index+1,current_combo,current_combo_index+1,k) + getCombinationsUtil(array,array_index+1,current_combo,current_combo_index,k)
When I tested this out for the list [1,2,3] and k = 2, for both implementations, I kept getting back the result [[3,3],[3,3],[3,3]]. However, if I actually print out the 'current_combo' variable within the inner (current_combo_index == k) if statement, the correct combinations print out. What gives? I am misunderstanding something to do with variable scope or Python lists?
The second method goes wrong because the line
return [current_combo]
returns a reference to current_combo. At the end of the program, all the combinations returned are references to the same current_combo.
You can fix this by making a copy of the current_combo by changing the line to:
return [current_combo[:]]
The first method fails for the same reason, you need to change:
self.final.append(current_combo)
to
self.final.append(current_combo[:])
Check this out: itertools.combinations. You can take a look at the implementation as well.
I am debugging the following function:
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
return unique.sort(key=len)
the list is sorted but the unique.sort(key=len) is returning nothing.
wont the function list.sort return anything.How can I fix it???
sort returns None because it mutates the list in-place. Try:
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
unique.sort(key=len)
return unique
Alternatively, use sorted, which does return a list.
def buggy_dedup_sort_by_len(input):
unique = list(set(input))
return sorted(unique, key=len)