Does a True value exist in a list of dictionaries? - python

I create a list of dictionaries like this:
list = []
for i in xrange(4):
list.append({})
list[i]['a'] = False
Now after a while, I want to (using a single line of code) see if any of the 'a' values are True.
I have tried:
anyTrue = True in list # always returns false
anyTrue = True in list[:]['a']
Is there such a convenient way of doing this?
Thanks!

Using any with generator expression:
>>> lst = []
>>>
>>> for i in xrange(4):
... lst.append({})
... lst[i]['a'] = False
...
>>> any(d['a'] for d in lst)
False
>>> lst[1]['a'] = True
>>> any(d['a'] for d in lst)
True
BTW, don't use the list as a variable name. It shadows builtin function/type list.

You can use any and a generator expression:
if any(x['a'] for x in list):
# Do stuff
See a demonstration below:
>>> lst = []
>>> for i in xrange(4):
... lst.append({})
... lst[i]['a'] = False
...
>>> any(x['a'] for x in lst)
False
>>> lst[2]['a'] = True # Set an 'a' value to True
>>> any(x['a'] for x in lst)
True
>>>
Also, you should refrain from naming a variable list. Doing so overshadows the built-in.

Related

Searching for obstacles in list of lists?

I'm writing a function that when given a list of lists it can determine if a specific first character is followed by a specific second character (either once or repeated) or is followed by another random string. When another random string is present the function should return False but when no random string is present the function should return True.
Basically if any other character other then . comes after B in its current list or any following lists then it should return False but if only . is present then it should return True.
For example, if the first character was B and the second character was . and the list of lists was [['.','.','B','.'],['.','.','.','.']] then it should return True but if the list of lists was [['a','c','B','r'],['.','s','g','h']] it should return False since a series of random strings follows B.
Any tips or help would be appreciated this is the code I have so far:
def free_of_obstacles(lst):
A = 'B'
B = '.'
for i, v in enumerate(lst):
if A in v:
continue
if B in v:
continue
return True
else:
return False
You could join all the chars in each list and join all the joined strings into a single string and then apply a regex to check if there is a match or not:
>>> lst=[['.','.','B','.'],['.','.','.','.']]
>>> import re
>>> bool(re.search(r'B(\.+)$', ''.join(''.join(i) for i in lst)))
True
>>> lst=[['a','c','B','r'],['.','s','g','h']]
>>> bool(re.search(r'B(\.+)$', ''.join(''.join(i) for i in lst)))
False
>>>
EDIT 1 ----> Above solution as a function returning True or False:
>>> import re
>>> def free_of_obstacles(lst):
... return bool(re.search(r'B(\.+)$', ''.join(''.join(i) for i in lst)))
...
>>> lst=[['a','c','B','r'],['.','s','g','h']]
>>> free_of_obstacles(lst)
False
>>> lst=[['.','.','B','.'],['.','.','.','.']]
>>> free_of_obstacles(lst)
True
Without using any imported modules:
Sample run 1
>>> lst=[['.','.','B','.'],['.','.','.','.']]
>>> newlst=[j for i in lst for j in i]
>>> newlst=newlst[newlst.index('B')+1:]
>>> newlst
['.', '.', '.', '.', '.']
>>> list(map(lambda x:x=='.', newlst))
[True, True, True, True, True]
>>> all(list(map(lambda x:x=='.', newlst)))
True
Sample run 2
>>> lst=[['a','c','B','r'],['.','s','g','h']]
>>> newlst=[j for i in lst for j in i]
>>> newlst=newlst[newlst.index('B')+1:]
>>> newlst
['r', '.', 's', 'g', 'h']
>>> list(map(lambda x:x=='.', newlst))
[False, True, False, False, False]
>>> all(list(map(lambda x:x=='.', newlst)))
False
EDIT 2 ----> Above solution as a function returning True or False:
>>> def free_of_obstacles(lst):
... newlst=[j for i in lst for j in i]
... newlst=newlst[newlst.index('B')+1:]
... return all(list(map(lambda x:x=='.', newlst)))
...
>>> lst=[['.','.','B','.'],['.','.','.','.']]
>>> free_of_obstacles(lst)
True
>>> lst=[['a','c','B','r'],['.','s','g','h']]
>>> free_of_obstacles(lst)
False
>>>

What is the Python equivalent of LINQ OfType<T>() (in .NET)

I am trying to get a single Handler of a specific custom type MemoryListHandler in the logger.handlers collection.
With .NET I would simply use the following LINQ extension, which filters element and returns only those of type MemoryListHandler:
logger.handlers.OfType<MemoryListHandler>().SingleOrDefault()
What would be the most elegant equivalent in Python?
My current (not very neat) attempt is:
next((handler for handler in logger.handlers if handler is MemoryListHandler), None)
You might try the index method.
try:
lh = logger.handlers
x = lh[lh.index(MemoryListHandler)]
except ValueError:
x = some_default_value
Python is dynamically typed, therefore you might not need to convert anything.
However, in some cases you still might need to convert, say, int to string :
map(lambda x: str(x), [1, 2, 3])
Or, given your function accepts only one argument, just pass the function alone :
map(str, [1, 2, 3])
Update
filter(lambda x: type(x) == YourClass, [your_array])
For Python the is operator tests identity NOT type like it does in c#. You want isinstance for your test -- which will also work with subtypes of the target_type you're looking for.
Using the Python REPL to illustrate the difference between is and isinstance:
>>> s = ""
>>> s is str
False
>>> isinstance(s, str)
True
>>> class Foo:
... def __init__(self):
... pass
...
>>> f = Foo()
>>> g = Foo()
>>> f is g
False
>>> f is Foo
False
>>> g is Foo
False
>>> x = f
>>> f is x
True
>>> g is x
False
Your own expression is pretty close to what you want. You can hide it behind a method:
def first_of_type(xs, target_type):
return next((x for x in xs if isinstance(x, target_type)), None)
Usage becomes short and sweet:
first_of_type(logger.handlers, MemoryListHandler)
Note: addition of type hints and doc comments would help usability.

Comparing 2 lists out of order

I want to compare 2 lists, say A and B.
A = [1,2,3]
B = [3,1,2]
I want to write a function to check if all the items in A are present in B or not.
i.e. the function should return True for the example above.
Note: The items of my lists are non-hashable objects.
For this, I wrote this code:
for elem in A:
if elem not in B:
return False
return True
The code works fine.
But I want a more efficient and a more pythonic way to do this.
You may use all
all(i in B for i in A)
Example:
>>> A = [1,2,3]
>>> B = [3,1,2]
>>> all(i in B for i in A)
True
>>> B = [3,1,4]
>>> all(i in B for i in A)
False
>>>
You could use Counter, which runs in O(n) time.
from collections import Counter
A = [1,2,3]
B = [3,1,2]
print(Counter(A) == Counter(B)) # Prints True
I think using set is a good solution for this task :
In [2]: A = [1,2,3]
In [3]: B = [3,1,2]
In [5]: set(A)==set(B)
Out[5]: True
This code will have O(n) complexity for more information you can check this link
If you don't want to use set you can try to sort lists :
def cmp(A,B):
A1 = sorted(A)
B1 = sorted(B)
for item in A1:
if binary_search(B1,item)==-1:
return False
for item in B1:
if binary_search(A1,item)==-1:
return False
return True

Modifying a list outside of recursive function in Python

There is a multidimensional list with not clear structure:
a=[[['123', '456'], ['789', '1011']], [['1213', '1415']], [['1617', '1819']]]
And there is a recursive function, which operates the list:
def get_The_Group_And_Rewrite_It(workingList):
if isinstance(workingList[0],str):
doSomething(workingList)
else:
for i in workingList:
get_The_Group_And_Rewrite_It(i)
Through time the get_The_Group_And_Rewrite_It() should get a list, for instance, ['123','456'], and as soon as it get it, doSomething function should rewrite it with ['abc'] in entire list.
The same with other lists of format[str,str,...]. In the end I should get something like
a=[[['abc'], ['abc']], [['abc']], [['abc']]]
I see it would be easy in C++, using *links, but how to do that in Python?
For this case, you can use slice assignment:
>>> a = [[['123', '456']]]
>>> x = a[0][0]
>>> x[:] = ['abc']
>>> a
[[['abc']]]
>>> def f(workingList):
... if isinstance(workingList[0],str):
... workingList[:] = ['abc']
... else:
... for i in workingList:
... f(i)
...
>>> a=[[['123', '456'], ['789', '1011']], [['1213', '1415']], [['1617', '1819']]]
>>> f(a)
>>> a
[[['abc'], ['abc']], [['abc']], [['abc']]]

Retrieving from list of objects by id

In the following code I create a list of three objects and use the variable a,b,c to store the first, second and then the third object by their id's but when I try to store the third object in variable c, it stores a list of the second and third object.
class Obj1():
id='obj1'
class Obj2():
id='obj2'
class Obj3():
id='obj3'
list1=[Obj1(),Obj2(),Obj3()]
a=list1[id=="obj1"]
print a
b=list1[id!='obj1']
print b
c=list1[id!='obj1'and id!='obj2':]
print c
When I run this code I get :
<__main__.Obj1 instance at 0x02AD5DA0>
<__main__.Obj2 instance at 0x02AD9030>
[<__main__.Obj2 instance at 0x02AD9030>, <__main__.Obj3 instance at 0x02AD90A8>]
why does variable c contain two objects?
Using a dictionary is probably the best idea in this case, as mentioned by Medhat. However, you can do things in a similar way to what you attempted using list comprehensions:
a = [e for e in list1 if e.id == "obj1"]
print a
b = [e for e in list1 if e.id != "obj1"]
print b
c = [e for e in list1 if e.id != "obj1" and e.id != "obj2"]
# Or:
# [e for e in list1 if e.id not in ("obj1", "obj2")]
print c
You should use a dictionary instead:
obj1 = Obj1()
obj2 = Obj2()
obj3 = Obj3()
list1 = {obj1.id: obj1, obj2.id: obj2, obj3.id: obj3}
Then access your objects like this:
a = list1[obj1.id]
b = list1[obj2.id]
c = list1[obj3.id]
id!='obj1'and id!='obj2' returns true which equals 1 in Python, that is to say, c=list1[id!='obj1'and id!='obj2':] equals c=list1[1:] , which of course has two objects.
BTW, id is the name of a built-in function. Please avoid using it as a name of varible.
Your list1 contains 3 elements:
>>> list1
[<__main__.Obj1 instance at 0x103437440>, <__main__.Obj2 instance at 0x1034377a0>, <__main__.Obj3 instance at 0x103437320>]
>>> id!='obj1'
True
>>> id!='obj2'
True
>>> True and True
True
>>> list1[True:]
[<__main__.Obj2 instance at 0x1034377a0>, <__main__.Obj3 instance at 0x103437320>]
>>>
True is 1 and False is 0 index:
Here is the example:
>>> ls = [1,2]
>>> ls[True]
2
>>> ls[False]
1
>>>
So, list[True:] is equal to list[1:] which is from first element till last.
In your case the the last two elements in the list1.

Categories