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}}
Related
Given lists(a list can have an element that is in another list) and a string, I want to find all names of lists that contains a given string.
Simply, I could just go through all lists using if statements, but I feel that there is more efficient way to do so.
Any suggestion and advice would be appreciated. Thank you.
Example of Simple Method I came up with
arrayA = ['1','2','3','4','5']
arrayB = ['3','4','5']
arrayC = ['1','3','5']
arrayD = ['7']
foundArrays = []
if givenString in arrayA:
foundArrays.append('arrayA')
if givenString in arrayB:
foundArrays.append('arrayB')
if givenString in arrayC:
foundArrays.append('arrayC')
if givenString in arrayD:
foundArrays.append('arrayD')
return foundArrays
Lookup in a list is not very efficient; a set is much better.
Let's define your data like
data = { # a dict of sets
"a": {1, 2, 3, 4, 5},
"b": {3, 4, 5},
"c": {1, 3, 5},
"d": {7}
}
then we can search like
search_for = 3 # for example
in_which = {label for label,values in data.items() if search_for in values}
# -> in_which = {'a', 'b', 'c'}
If you are going to repeat this often, it may be worth pre-processing your data like
from collections import defaultdict
lookup = defaultdict(set)
for label,values in data.items():
for v in values:
lookup[v].add(label)
Now you can simply
in_which = lookup[search_for] # -> {'a', 'b', 'c'}
The simple one-liner is:
result = [lst for lst in [arrayA, arrayB, arrayC, arrayD] if givenString in lst]
or if you prefer a more functional style:
result = filter(lambda lst: givenString in lst, [arrayA, arrayB, arrayC, arrayD])
Note that neither of these gives you the NAME of the list. You shouldn't ever need to know that, though.
Array names?
Try something like this with eval() nonetheless using eval() is evil
arrayA = [1,2,3,4,5,'x']
arrayB = [3,4,5]
arrayC = [1,3,5]
arrayD = [7,'x']
foundArrays = []
array_names = ['arrayA', 'arrayB', 'arrayC', 'arrayD']
givenString = 'x'
result = [arr for arr in array_names if givenString in eval(arr)]
print result
['arrayA', 'arrayD']
class A(object):
a = 1
b = 0
c = None
d = None
a_obj=A()
a_list = ['a', 'b', 'c', 'd']
attrs_present = filter(lambda x: getattr(a_obj, x), a_list)
I want both a and b attributes, here 0 is a valid value. I don't want to use comparison==0
is there a way to get those?
Any help will be appriciated, Thanks.
If you want to exclude c, d (Nones), use is None or is not None:
attrs_present = filter(lambda x: getattr(a_obj, x, None) is not None, a_list)
# NOTE: Added the third argument `None`
# to prevent `AttributeError` in case of missing attribute
# (for example, a_list = ['a', 'e'])
If you want to include c, d, use hasattr:
attrs_present = filter(lambda x: hasattr(a_obj, x), a_list)
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
I have two questions:
1) I want to write a statement like: superVar = [subVar1 = 'a', subVar2 = 'b']
After this statement, I want:
superVar = ['a', 'b']
subVar1 = 'a'
subVar2 = 'b'
Is this somehow achievable in python?
2) I want to do the following inside a class's init function:
self.superVar = [v1 = 'a', v2 = 'b']
After this statement, I want:
self.superVar = ['a', 'b']
self.superVar.v1 = 'a'
self.superVar.v2 = 'b'
i.e. have 'superVar' be part of the name of the other variables.
As you might have guessed, what I really want to do is (2) above. (1) is just the first step and I would be happy even with that, if (2) is not possible.
Thanks a lot!
Gaurav
>>> from collections import namedtuple
>>> T = namedtuple('supervar', ['v1', 'v2'])
>>> superVar = T('a', 'b')
>>> superVar.v1
'a'
>>> superVar.v2
'b'
Do you mean a dictionary?
superVar = {'subVar1': 'a', 'subVar2': 'b'}
superVar['subVar1']
# 'a'
superVar['subVar2']
# 'b'
In a class:
class Foo(object):
def __init__(self, a, b):
self.superVar = {'subVar1' : a, 'subVar2' : b}
bar = Foo('one', 'two')
bar.superVar.values()
# ['one', 'two']
If you want to keep order, you can use an ordered dictionary from the collections module.
Why not create a dictionary for your subVars and make superVar a list of values from the subVar dictionary?
d = {'subVar1': 'value1', 'subVar2': 'value2'}
superVar = d.values()
In Python, assignments are statements, not expressions. You can't chain together statements. So (1) is impossible.
However, you can use keyword arguments in the __init__ method of a class to get the behavior in (2):
>>> class Test:
def __init__(self, **kwargs):
print "the keyword arguments are", kwargs #kwargs is a dictionary
for x in kwargs:
setattr(self, x, kwargs[x]) #adds an attribute from kwargs to self
>>> t = Test(var1=1234,var2='hello',var3=45.234)
the keyword arguments are {'var1': 1234, 'var3': 45.234, 'var2': 'hello'}
>>> t.var1
1234
>>> t.var2
'hello'
>>> t.var3
45.234
>>>
This is basically the same as Jeremy Bentham's answer,
class T:
def __init__(self):
self.SuperVar = {'v1':'a', 'v2':'b'}
print self.SuperVar.v1
print self.SuperVar.v2
def __setattr__(self, k, v):
class SuperVar:
def __setattr__(self, k, v):
self.__dict__[k] = v
if k == "SuperVar":
self.__dict__["SuperVar"] = SuperVar()
for k in v:
self.__dict__["SuperVar"].__setattr__(k, v[k])
else:
self.__dict__[k] = v
t = T()
I am probably approaching this wrong, but would appreciate being straightened out.
I would like to be able to use both the values and the names of some attributes of a class
Sample:
class DoStuff(object):
def __init__(self):
self.a="Alpha"
self.b="Beta"
self.c="Gamma"
def printStuff(self):
for thing in [self.a, self.b, self.c]:
print NAMEOFTHING, thing
What I want is:
a Alpha
b Beta
c Gamma
How can I get that?
Edit: Some confusion because my example showed me printing ALL the values. Instead I want this:
a Alpha
c Gamma
with the list for my print method just having 'a' and 'c' in it.
The way your class and for loop are set up, there is nothing you can put in place of NAMEOFTHING to get to the names of those variables. Here are a few alternatives on how you can modify your approach:
Use a dictionary instead of individual attributes, and then provide a list of keys in your for loop:
class DoStuff(object):
def __init__(self):
self.names = {"a": "Alpha",
"b": "Beta",
"c": "Gamma"}
def printStuff(self):
for name in ['a', 'b', 'c']:
print name, self.names[name]
Use the attribute names in your list and then use getattr():
class DoStuff(object):
def __init__(self):
self.a="Alpha"
self.b="Beta"
self.c="Gamma"
def printStuff(self):
for name in ['a', 'b', 'c']:
print name, getattr(self, name)
The closest you could get is:
for thing in ['a', 'b', 'c']:
print thing, getattr(self, thing)
Variables can have multiple names and aren't aware of their own name, so if you know it's 'a', then you can use getattr to resolve the lookup.
Another option (although not greatly different than above)
to_get = ['a', 'b', 'c']
from operator import attrgetter
blah = zip(to_get, attrgetter(*to_get)(self))
Following on Jon's answer, you might also find it helpful to set the list of attributes you want to include in the output as an optional argument:
def printStuff(self, included=['a', 'c']):
for thing in included:
print thing, getattr(self, thing)
which makes it easy to generate both outputs, by saying DoStuff().printStuff() to get just the values of a and c, or DoStuff().printStuff(['a', 'b', 'c']) to get all three. Of course, this allows for varying output—if it's an explicit design-goal that the set of fields being printed is invariant, this would be counterproductive.
# You can use __dict__
>>> class x:
>>> def __init__(self):
>>> self.a = 1
>>> self.b = 2
>>> self.c = 3
>>> self.d = 4
>>> def prnt(self):
>>> limit = "b", "c"
>>> return {k:v for (k, v) in self.__dict__.iteritems()if k in limit}
>>> r = x()
>>> print r.prnt()
{'b': 2, 'c': 3}
# __dict__ can be also done outside the class
limit = "b", "c"
print {k:v for (k, v) in r.__dict__.iteritems()if k in limit}