python comprehension loop for dictionary - python

Beginner question.
I have a dictionary as such:
tadas = {'tadas':{'one':True,'two':2}, 'john':{'one':True,'two':True}}
I would like to count the True values where key is 'one'. How should I modify my code?
sum(x == True for y in tadas.values() for x in y.values() )

Access only the one attribute:
sum(item['one'] for item in tadas.values())
This makes use of the fact, that True is equal to 1 and False is equal to 0.
If not every item contains the key 'one' you should use the .get method:
sum(item.get('one', 0) for item in tadas.values())
.get returns the second argument, if the dict does not contain the first argument.
If 'one' can also point to numbers, you should explictly test for is True:
sum(item.get('one', 0) is True for item in tadas.values())
If you dont want to hide the summation in the boolean, you can do it more explicitly with:
sum(1 if item.get('one', False) is True else 0 for item in tadas.values())

List can count occurrences of values, so making use of that is probably most idiomatic:
[x.get('one') for x in tadas.values()].count(True)

You can use filter to filter the list of any values where 'one' doesn't map to True. Then, just return the length of the list.
len(filter(lambda x: tadas[x]['one'], tadas))

try this:
print(sum(1 for x in tadas.values() if x['one']))
NOTE: please do not use this answer as it's definitely not as good as other answers.

Related

Test for list without duplicated elements

There aren't a set of instructions, but I basically have to write a code for def hasNoDuplicate and it returns True exactly when list has no duplicates. This is what I've written, I'm new to programming so all of this is very overwhelming. I don't know exactly what to put in the if statement. Any advice would help a lot!
def hasNoDuplicates(values):
foundCounterExampleYet = False
for value in values:
if():
foundCounterExampleYet = True
return not(foundCounterExampleYet)
def hasNoDuplicates(values):
foundCounterExampleYet = False
value = None
while values:
value = values.pop()
if value in values:
foundCounterExampleYet = True
break
return not(foundCounterExampleYet)
Now you get:
>>> hasNoDuplicates([1,2,3])
True
>>> hasNoDuplicates([1,2,3,4,6,7,8,9,4])
False
>>>
What this code does is, it takes the input list, and one by one takes out the last element from the list and checks if the item exists in the list. If it exists, then a duplication is detected, and it changes the value of foundCounterExampleYet and consequently jumps out of the loop. This checking happens until the list becomes empty. while values means do this while the list is not empty
The pop method takes out the last element from the list. But it has side effect, meaning it changes the value of the initial input:
>>> [1,2,3].pop()
3
>>> a = [1,2,3]
>>> a.pop()
3
>>> a
[1, 2]
You're on the right track. You can store the values in a set as you're looping through the inputs, and use the in operator to check for membership in that set. See my comments alongside the following code.
def hasNoDuplicates(values):
currentValues = set() # initialize an empty set
for value in values: # iterate over your inputs
if value in currentValues: # if the current value is in your set, there is a duplicate
return False
else:
currentValues.add(value) # no duplicate exists, add it to the set
return True # If it made it through all the values, there were no duplicates
For fun, there is an easier way to do this. If the items in the values sequence are hashable, you can make a set from the whole sequence. Since by definition a set may not have any duplicates, if the length of the original sequence is the same length as the set, then all items are unique. If the set is shorter, there was at least one duplicate.
def hasNoDuplicates(values):
return len(values) == len(set(values))

See if all items in a list = certain string

How would I find if I have a list of a given string, 'hello':
x = ['hello', 'hello', 'hello']
# evaluates to True
x = ['hello', '1']
# evaluates to False
Use the all() function to test if a condition holds True for all elements:
all(el == 'hello' for el in x)
The all() function takes an iterable (something that produces results one by one) and will only return True itself if all those elements are true. The moment it finds anything that is false, it'll return False and not look further.
Here the iterable is a generator expression, one that executes an equality test for each element in the input sequence. The fact that all() stops iterating early if a false value is encountered makes this test very efficient if the test in the contained generator expression is False for any element early on.
Note that if x is empty, then all() returns True as well as it won't find any elements that are false in an empty sequence. You could test for the sequence being non-empty first:
if x and all(el == 'hello' for el in x):
to work around that.
This ought to work:
# First check to make sure 'x' isn't empty, then use the 'all' built-in
if x and all(y=='hello' for y in x):
Nice thing about the all built-in is that it stops on the first item it finds that doesn't meet the condition. This means it is quite efficient with large lists.
Also, if all of the items in the list are strings, then you can use the lower method of a string to match things like `'HellO', 'hELLO', etc.
if x and all(y.lower()=='hello' for y in x):
Yet another way to do what you want (all is the most idiomatic way to do that, as all other answers note), useful in case if you need to check more than once:
s = set(l)
cond = (len(s) == 1) and (item in s)
It helps to avoid O(n) traversal every time you want to check the condition.
Using filter and len is easy.
x = ['hello', 'hello', 'hello']
s = 'hello'
print len(filter(lambda i:i==s, x))==len(x)
Youn can do that using set:
set(x) == {'hello'}

How do I check existence of a string in a list of strings, including substrings?

I have written a function to check for the existence of a value in a list and return True if it exists. It works well for exact matches, but I need for it to return True if the value exists anywhere in the list entry (e.g. value <= listEntry, I think.) Here is the code I am using for the function:
def isValInLst(val,lst):
"""check to see if val is in lst. If it doesn't NOT exist (i.e. != 0),
return True. Otherwise return false."""
if lst.count(val) != 0:
return True
else:
print 'val is '+str(val)
return False
Without looping through the entire character string and/or using RegEx's (unless those are the most efficient), how should I go about this in a pythonic manner?
This is very similar to another SO question, but I need to check for the existence of the ENTIRE val string anywhere in the list. It would also be great to return the index / indices of matches, but I'm sure that's covered elsewhere on Stackoverflow.
If I understood your question then I guess you need any:
return any(val in x for x in lst)
Demo:
>>> lst = ['aaa','dfbbsd','sdfdee']
>>> val = 'bb'
>>> any(val in x for x in lst)
True
>>> val = "foo"
>>> any(val in x for x in lst)
False
>>> val = "fde"
>>> any(val in x for x in lst)
True
Mostly covered, but if you want to get the index of the matches I would suggest something like this:
indices = [index for index, content in enumerate(input) if substring in content]
if you want to add in the true/false you can still directly use the result from this list comprehension since it will return an empty list if your input doesn't contain the substring which will evaluate to False.
In the terms of your first function:
def isValInLst(val, lst):
return bool([index for index, content in enumerate(lst) if val in content])
where the bool() just converts the answer into a boolean value, but without the bool this will return a list of all places where the substring appears in the list.
There are multiple possibilities to do that. For example:
def valInList1 (val, lst):
# check `in` for each element in the list
return any(val in x for x in lst)
def valInList2 (val, lst):
# join the list to a single string using some character
# that definitely does not occur in val
return val in ';;;'.join(lst)

(Python 2.7) Use a list as an argument in a function?

So I'm trying to learn Python using codecademy but I'm stuck. It's asking me to define a function that takes a list as an argument. This is the code I have:
# Write your function below!
def fizz_count(*x):
count = 0
for x in fizz_count:
if x == "fizz":
count += 1
return count
It's probably something stupid I've done wrong, but it keeps telling me to make sure the function only takes one parameter, "x". def fizz_count(x): doesn't work either though. What am I supposed to do here?
Edit: Thanks for the help everyone, I see what I was doing wrong now.
There are a handful of problems here:
You're trying to iterate over fizz_count. But fizz_count is your function. x is your passed-in argument. So it should be for x in x: (but see #3).
You're accepting one argument with *x. The * causes x to be a tuple of all arguments. If you only pass one, a list, then the list is x[0] and items of the list are x[0][0], x[0][1] and so on. Easier to just accept x.
You're using your argument, x, as the placeholder for items in your list when you iterate over it, which means after the loop, x no longer refers to the passed-in list, but to the last item of it. This would actually work in this case because you don't use x afterward, but for clarity it's better to use a different variable name.
Some of your variable names could be more descriptive.
Putting these together we get something like this:
def fizz_count(sequence):
count = 0
for item in sequence:
if item == "fizz":
count += 1
return count
I assume you're taking the long way 'round for learning porpoises, which don't swim so fast. A better way to write this might be:
def fizz_count(sequence):
return sum(item == "fizz" for item in sequence)
But in fact list has a count() method, as does tuple, so if you know for sure that your argument is a list or tuple (and not some other kind of sequence), you can just do:
def fizz_count(sequence):
return sequence.count("fizz")
In fact, that's so simple, you hardly need to write a function for it!
when you pass *x to a function, then x is a list. Do either
def function(x):
# x is a variable
...
function('foo') # pass a single variable
funciton(['foo', 'bar']) # pass a list, explicitly
or
def function(*args):
# args is a list of unspecified size
...
function('foo') # x is list of 1 element
function('foo', 'bar') # x is list with two elements
Your function isn't taking a list as an argument. *x expands to consume your passed arguments, so your function is expecting to be called like this:
f(1, 2, 3)
Not like this:
f([1, 2, 3])
Notice the lack of a list object in your first example. Get rid of the *, as you don't need it:
# Write your function below!
def fizz_count(lst):
count = 0
for elem in lst:
if elem == "fizz":
count += 1
return count
You can also just use list.count:
# Write your function below!
def fizz_count(lst):
return lst.count('fizz')
It must be a typo. You're trying to iterate over the function name.
try this:
def fizz_count(x):
counter = 0
for element in x:
if element == "fizz":
counter += 1
return counter
Try this:
# Write your function below!
def fizz_count(x):
count = 0
for i in x:
if i == "fizz":
count += 1
return count
Sample :
>>> fizz_count(['test','fizz','buzz'])
1
for i in x: will iterate through every elements of list x. Suggest you to read more here.

rewrite small piece of python code

I have lots of small pieces of code that look like:
for it in <iterable>:
if <condition>:
return True/False
Is there a way I can rewrite this piece of code with a lambda expression ? I know I can factor it out in a small method/function, but I am looking for some lambda thing if it can be done.
Use the built-in any function.
e.g.
any(<condition> for it in <iterable>) # return True on <condition>
In addition to what everyone else has said, for the reverse case:
for it in <iterable>:
if <condition>:
return False
return True
use all():
b = all(<condition> for it in <iterable>)
if you want to check the condition for every item of iterable you can use
listcomprehensions to to this
b = [ x == whatever for x in a ]
you can combine this with any if you only need to know if there is one element
that evals to true for your condition
b = any(x == whatever for x in a)
Here is a simple example which returns True if any of the objects in it is equal to 2. by using the map function:
any(map(lambda x: x==2, it))
Change the lambda expression to reflect your condition.
Another nice way is to use any with a list comprehension:
any([True for x in it if x==2])
or alternatively, a generator expression:
any(x==2 for x in it)

Categories