if logic not working in array context for python - python

I have a function where depending on the type t a different function needs to be applied. I tried the following, but it does not work in a list context.
def compute(d, t='c'):
"""
d is the computing variable
t is the type, can be a list
"""
if t == 'a':
p = fa(d)
elif t == 'b':
p = fb(d)
else:
p = fc(d)
return p
For instance, t could be
t = ['a', 'b', 'a' , 'c', 'b']
and should return
p = [fa(d), fb(d), fa(d), fc(d), fb(d)]
Any suggestions?
Cheers,
Mike

This should work
def compute(d, t='c'):
"""
d is the computing variable
t is the type, can be a list
"""
l = []
for x in t:
if t == 'a':
l.append(fa(d))
elif t == 'b':
l.append(fb(d))
else:
l.append(fc(d))
if len(l) == 1:
return l[0]
else:
return l
compute(d, ['a', 'b', 'a' , 'c', 'b'])
It processes everything that is in t, be it a single item or a list.
Be aware that it returns the return values of the called functions, not the functions and their arguments

Related

calling a python function that does the drawing in another function

I'm trying to make a function that draws a random number between 1 and 3 and calls it in another function in which if the number chosen in the drawing of the first function is 1, it returns a list with up to 3 options among the possible ones in the listOne, if it is 2 returns up to three possible ones from the listTwo and if it is 3 the same thing for the listThree, but the output is not coming out correctly
Thats my code:
from random import random, randint, sample, choices
import csv
class Test(object):
def __init__(self):
self.data = dict()
def foo1(self):
return randint(1,3)
def foo2(self):
n = 3
for i in range(n):
r = self.foo1()
if (r == 1):
listOne = ['A', 'B', 'C']
smpOne = choices(listOne, k = randint(1,3))
return smpOne
elif (r == 2):
listTwo = ['D', 'E', 'F']
smpTwo = choices(listTwo, k = randint(1,3))
return smpTwo
elif (r == 3):
listThree = ['G', 'H', 'I']
smpThree = choices(listThree, k = randint(1,3))
return smpThree
def concat(self, nToGenerate):
for i in range(nToGenerate):
self.data[i] = {'foo 1': self.foo1(), 'foo2': self.foo2()}
return self.data
if __name__ == '__main__':
try:
nToGenerate = int(input("How tests?"))
except ValueError:
print("Sorry, not a number")
test = Test()
myDict = test.concat(nToGenerate)
with open('test.csv', "w", newline='') as csvfile:
fieldnames = list(myDict.values())[0].keys()
writerFile = csv.DictWriter(csvfile, fieldnames)
writerFile.writeheader()
for key in myDict:
writerFile.writerow({field: myDict[key].get(field) or key for field in fieldnames})
and that is the output for 10 tests:
foo 1,foo2
2,['H']
1,"['A', 'B', 'B']"
2,"['A', 'A']"
2,"['F', 'E']"
**1,"['I', 'I']"**
2,['B']
2,"['H', 'G']"
2,['B']
2,"['D', 'F']"
3,"['I', 'G']"
As we can see there is an exit that has the number 1 drawn and comes out with a list ['I', 'I']
however, the letter I could only appear on a list whose draw with the number 3
When you call foo1 in:
def concat(self, nToGenerate):
for i in range(nToGenerate):
self.data[i] = {'foo 1': self.foo1(), 'foo2': self.foo2()}
...
And then again in:
def foo2(self):
n = 3
for i in range(n):
r = self.foo1()
...
Both invocations to foo1 return a new pseudo-random number. There is no reason to think that they should always be the same random number.
The easiest solution would be to simply have foo2 take an argument. This argument will be the pseudo-random number, which will be generated in concat and then passed to foo2. You can eliminate the for-loop in foo2, since it does nothing (you return during the first iteration anyway). You can eliminate the if-statements by creating a dictionary, mapping the three possible values of r to different lists:
def foo2(self, r):
return choices({
1: ["A", "B", "C"],
2: ["D", "E", "F"],
3: ["G", "H", "I"]
}[r], k=randint(1, 3))
You would also have to change concat. For each iteration of the for-loop, we generate a new random number. That random number becomes the value for the "foo 1" key-value pair, and gets passed into foo2 to get the value for the "foo 2" key-value pair:
def concat(self, nToGenerate):
for i in range(nToGenerate):
r = self.foo1()
self.data[i] = {"foo 1": r, "foo 2": self.foo2(r)}
return self.data
I believe the issue is arising because you are calling foo1 twice, once in foo2 and once when assigning it the self.data. These will result in two different results from the random integer function so there is no guarantee that the printed value will match the value passed to foo2. You could solve this by returning the foo1 value in foo2 along with your return in the form of a tuple and then use indices when assigning to self.data. Hope I correctly understood and was helpful.

How to return a list as frozenset type?

I wants to return a list as frozenset type and its type will be checked by returning function as given below
frozentSet = functionName(list1, list2)
if type(frozentSet) == frozenset:
print("Return value is a frozenset")
else:
print("Retrun value is not a frozenset")
Whenever I am returning any list as "frozenset" it gives the result as below, while I wants to return as given in above if condition.
return frozenset(['a','b','c','d','e','f'])
Output:
['f']
['b']
['a']
['d']
['e']
Returned value is not a frozenset
Thanks for your prompt response. Please see the whole code below.
def returnFrozenset(listA):
frsA = frozenset(listA)
return frsA
if __name__ == '__main__':
lst1_count = int(input().strip())
lst1 = []
for _ in range(lst1_count):
lst1_item = input()
lst1.append(lst1_item)
isFrozenSet = returnFrozenset(lst1)
print("Returned value is {1} frozenset".format(isFrozenSet, "a" if type(frset) == frozenset else "not a"))
Maybe with a little more code we can help you out, I'm doing the same as you and everything is working fine.
Example code:
def func(list1):
return frozenset(list1)
if __name__ == "__main__":
frozentSet = func(['a','b','c','d','e','f'])
if type(frozentSet) == frozenset:
print("Return value is a frozenset")
else:
print("Retrun value is not a frozenset")
output:
>> frozenset({'a', 'd', 'b', 'f', 'e', 'c'})
>> Return value is a frozenset

merging lists in a list of lists that has one similar item in python [duplicate]

This question already has answers here:
Find all the keys cluster in a list
(2 answers)
Closed 3 years ago.
I have a list of list with strings in it:
list = [["a","b"],["c","d"],["a", "e"],["f","d"],["x","y"]]
Now i want to merge all lists, that have 1 similar item in it like this:
grouped_list = [["a", "b", "e"],["c","d","f"],["x","y"]]
my code is this til now:
list = [["a","b"],["b","c"],["d","e"],["x","y"]]
clist = list.copy()
result = []
counter = 0
del_list = []
def oneofsame(L1, L2):
counter = 0
for i in L1:
for j in L2:
if i == j:
counter += 1
if counter == 0:
return False
else:
return True
for l in list:
try:
del clist[clist.index(l)]
except:
pass
result.append([])
for i in l:
for cl in clist:
if oneofsame(l, cl):
for j in l:
if j not in result[counter]:
result[counter].append(j)
for j in cl:
if j not in result[counter]:
result[counter].append(j)
del_list.append(cl)
else:
result.append(cl)
del_list.append(cl)
for j in del_list:
del clist[clist.index(j)]
del_list = []
counter += 1
del_list = []
cresult = result.copy()
for i in range(len(cresult)-1, 0, -1):
if cresult[i] == []:
del result[i]
print(result)
but this code doesn't merge all of my example input (I can't paste my example input, because its sensitiv data)
Here is a way to do it.
For each pair:
if we find a group that contains one of the values, we append the pair to the group
if we find a second group that contains the other value, we merge the groups.
if we found no matching group, then our pair constitutes a new one.
def group_equals(lst):
groups = []
for pair in lst:
pair = set(pair)
equals_found = 0
for idx, group in enumerate(groups):
if group.intersection(pair):
equals_found += 1
if equals_found == 1:
# We found a first group that contains one of our values,
# we can add our pair to the group
group.update(pair)
first_group = group
elif equals_found == 2:
# We found a second group that contains the other one of
# our values, we merge it with the first one
first_group.update(group)
del groups[idx]
break
# If none of our values was found, we create a new group
if not equals_found:
groups.append(pair)
return [list(sorted(group)) for group in groups]
tests = [ [["a", "b"], ["c", "d"], ["b", "c"]], # all equal
[["a","b"],["c","d"],["a", "e"],["f","d"]],
[["a","b"],["c","d"],["a", "e"],["f","d"],["x","y"]]
]
for lst in tests:
print(group_equals(lst))
# [['a', 'b', 'c', 'd']]
# [['a', 'b', 'e'], ['c', 'd', 'f']]
# [['a', 'b', 'e'], ['c', 'd', 'f'], ['x', 'y']]
I hope my below code will solve your problem:
import itertools
import copy
lista = [["a","b"],["c","d"],["a", "e"],["f","d"],["x","y"]] #[["a","b"],["e","d1"],["a", "e"],["a","d"],["d","y"]]
def grouped_list(lista):
aa = []
bbc = copy.deepcopy(lista)
flag = False
for a, b in itertools.combinations(lista,2):
bb = a+b
if len(set(bb)) < len(bb):
flag = True
cc = list(set(bb))
cc.sort()
if cc not in aa: aa.append(cc)
if a in lista: lista.remove(a)
if b in lista: lista.remove(b)
if lista: aa = aa + lista
if not flag: return bbc
else: return grouped_list(aa)
print ("Grouped list -->", grouped_list(lista))
Feel free to ask/suggest anything in the above code.

Lists in python - return value once

I would like to make a function that takes a empty list and returns the values only once (even if the same value is entered several times).
Example
input from user:
list=[a,b,b,c,d,d,d,e,f]
The function returns then:
list=[a,b,c,d,e,f]
(does not have to be in chronological order, does not matter)
What I have done so far is:
def func1():
list=[]
def func1():
list1=[]
while(1):
val = input("Enter the value\n")
if val == 'exit':
return list(set(list1))
list1.append(int(val))
print(func1())
you can use set that returns unique value
In [44]: def func1(l):
...: return [x for x in set(l)]
...:
In [45]: l=['a','b','b','c','d','d','d','e','f']
...:
In [46]: func1(l)
Out[46]: ['a', 'c', 'b', 'e', 'd', 'f']
In [47]:
You just simply make it below
def func1(mylist):
return list(set(mylist))
and call your method as :
newList = func1([1,1,2,2,3,4,5])

Python Dictionary of Dictionary with condition

I am working on a function. If "source" is found in "d" then it will be added to it's value of dictionary object, otherwise it will be added. For example in this case. "a" is added twice but "b" is added once.
I would like to get output as below(last line)
Thank you.
def adder(source,dest,weight):
""""""
if __name__ == "__main__":
d = {} #dictionary
adder('a','b',1)
adder('a','f',4)
adder('b','c',1)
adder('f','g',3)
print d
{'a':{'b':1,'f':4}, 'b':{'c':1}, 'f':{'g':3},g:{},c:{}} #<----final o/p needed
A dictionary of dictionaries is just a dictionary of tuples. You could implement adder like this:
#The dictionary we will be adding to
d = {}
def adder(source, dest, weight):
d[(source, dest)] = weight
The high brow reason for this is that in any category with products, Hom(C, Hom(B, A)) is naturally isomorphic to Hom(C x B, A). Or in a functional language,
f : C -> (B -> A)
Is the same as:
f : C x B -> A
And coincidentally, it is also why (A^B)^C = A^(B * C).
The following implementation should do so:
def adder(dict, source, dest, weight):
if not source in dict:
dict[source] = {}
if not dest in dict:
dict[dest] = {}
dict[source][dest] = weight
Please note that I added dict as first argument to your method.
You can just use a simple if condition:
In [9]: def adder(d,source,dest,weight):
...: if source in d:
...: d[source][dest] = weight
...: else:
...: d[source] = {dest: weight}
...:
In [10]: d={}
In [11]: adder(d, 'a', 'b', 1)
In [12]: adder(d, 'a', 'f', 4)
In [13]: adder(d, 'b', 'c', 1)
In [14]: d
Out[14]: {'a': {'b': 1, 'f': 4}, 'b': {'c': 1}}

Categories