Dictionary with list of tuples Python - python-3.x

if match:
occur=0
for item in tweets:
if candidate in item:
popular=item[4]+item[5]
occur+=popular
famous.append(occur)
return occur
I get 10161 only. Also for this function is there a way i can sort the list by numbers and return a list with candidates according the sorted number

the modification are simple, first you need to create a empty list where the result will be keep, then in the for loop you need to check if the condition is fulfilled and add that element to the list if its does, and finally return that list. I also choose some more meaningful variables names
def famous(data_tweet, lower, higher ):
result=[]
for person, tweets in data_tweet.items():
if all( lower <= tw[2] <= higher for tw in tweets ):
result.append( person )
return result
this can be reduced a little bit with the use of list comprehension
def famous(data_tweet, lower, higher ):
return [person for person, tweets in data_tweet.items() if all( lower <= tw[2] <= higher for tw in tweets )]
(notice the similarities)
in either case the result is
>>> famous(tweet,1470000000,1480000000)
['b', 'a']
>>>
As you are not allow to use all, then it should be done old school style, that is using flag, which is a variable which will tell us if the condition is fulfilled or not
def famous(data_tweet, lower, higher ):
result=[]
for person, tweets in data_tweet.items():
is_valid = True
for tw in tweets:
if not ( lower <= tw[2] <= higher):
is_valid = False
break
if is_valid:
result.append( person )
return result
here we first assume that the condition is fulfilled, then we check is that is effectively true, and if is not we change our flag to false and break that loop as there is no more reason to continue with further checks, which is the basically what all do for you. Afterwards, according to the value of the flag we append the person to the list or not.
(If you also are not allow to use break either, don't worry and just remove it, that would not affect the function)
about the counting stuff
result=[]
for person in tweet:
count = 0
for tw in tweet[person]:
count += tw[4] + tw[5]
result.append(count)

Related

How to convert a conditional statement to a simple expression? Is compounding a return this way Acceptable practice?

The exercise I am doing was given by a book that takes a dictionary argument and asks for me to give a return value of True or False. I am new to Python 3 and as a personal exercise for learning I want to convert all the conditions of a "valid dictionary as a chessboard into" a single return value. I haven't actually tested this code for errors as it isn't finished, but I did run it through an online validator I found https://extendsclass.com/python-tester.html.
I want to know how I can convert the following 2 code blocks into simple expressions to be used in the return statement in my function below, You can see below that I've converted most expressions into the return value already with "and" because "ALL expressions must == True"
for pieces in dictionary.values():
if all(pieces.startswith('b')) or \
all(pieces.startswith('w')):
return True
else:
return False
The above code block loops through the dictionary keys passed to function as "pieces",
and compares each key individually to determine if it starts with a value of 'b' or 'w'. So if any key does not start with 'b' or 'w' the dictionary "chessboard" is false as it contains an improper piece. Ok I think I see an error in this I'm going to look into it and try to figure it out. Ok I noticed some errors in the above code that need to be addressed I am currently researching how to properly execute the above code.
for square in dictionary:
try:
if int(square[:0]) <= 8 and \
square[-1] <= 'h':
return True
else:
return False
except ValueError:
return False
I worked on the above code block a very long time and am still not sure that's the "best" implementation of what I want it to do. But I am still new and did my best.
Anyway it slices the dictionary key and compares the first char in the key to make sure it isn't over 8 which is the maximum "valid range" if over valid range it returns false and anything not int is obviously automatically False and returned as such by the "exception".
Then it slices the dictionary key to get the last char of the dictionary key and compares it to <= 'h' as that is the valid range and anything over 'h' or not a valid type value will return as False.
And then it compares the results of True/False "and" True/False with "and" because both conditions must be True.
Here is the function as it currently is with a test dictionary at the end:
def cBV(dic): # (c)hess(B)oard(V)alidator
Err = 'Error: Invalid Board -'
if not isinstance(dic, type({})):
raise TypeError('Object passed to cBV is not of type <class dict>')
chess_pieces = {'bk pieces': 0, 'wh pieces': 0,
'bk pawns': 0, 'wh pawns': 0}
# converts dictionary values into keys and assigns those keys "counn of values"
for squares, pieces in dic.items:
if pieces.startswith('b'): # alt if pieces[:0] == 'b':
if pieces.startswith('bpawn'): # alt if pieces == 'bpawn':
chess_pieces['bk pawns'] += 1
chess_pieces['bk pieces'] += 1
elif pieces.startswith('w'):
if pieces.startswith('wpawn'):
chess_pieces['wh pawns'] += 1
chess_pieces['wh pieces'] += 1
return 'wking' in dic.values() and \
'bking' in dic.values() and \
chess_pieces['bk pieces'] <= 16 and \
chess_pieces['wh pieces'] <= 16 and \
chess_pieces['bk pawns'] <= 8 and \
chess_pieces['wh pawns'] <= 8 and \
dict = {'8h': 'wking', '2c': 'bking', '3a': 'wpawn', '3b': 'wpawn', '3c': 'wpawn',
'3d': 'wpawn', '3e': 'wpawn', '3f': 'wpawn', '3g': 'wpawn', '3h': 'wpawn', '4b': 'wpawn'}
test = cBV(dict)
print('Is this a valid chessboard? ' + str(test))
What you have now is good, and you should feel proud - there are more fancy techniques for making things more concise, and you'll get more used to them as you wrap your head around how the various data structures work.
for pieces in dictionary.values()
if pieces.startswith('b') or \
pieces.startswith('w'):
return True
else:
return False
can be converted to the one-liner
return all(
piece.startswith('b') or piece.startswith('w')
for piece in dictionary.values()
)
which does a few things.
The all() function takes any iterable object, and returns True if all of the values in that iterable are truthy. If even one of them is not, then it 'short-circuits' and returns False instead.
As our argument to all(), we give a "comprehension". A comprehension is essentially a one-line for loop, of the form f(element) for element in iterable: it performs whatever f(element) is, for every element in the iterable.
In our case, the iterable is dictionary.values(), which returns all of the values (but not the keys) in dictionary (which, here, is 'wking', 'wpawn', ...). In this case, these are strings.
piece is what we assign each element of, for each 'iteration' of the comprehension. It'll run for piece = 'wking', then for piece = 'wpawn', etc.
piece.startswith('b') or piece.startswith('w') is the function that we perform for each piece. This outputs either True or False, depending on whether the conditions are met.
You can wrap a comprehension in square-brackets [] to have it output as a regular list. However, if you give a comprehension as an argument to a function like all(), which is what we're doing here, then it will end up as a "generator", a slightly more efficient object that only calculates one object at a time. For our purposes, this isn't important.
The comprehension, overall, produces a series containing either True or False, that all() will consume.
Similarly with your second code snippet. You have the basics down, but can be more concise. Your code:
def allSquaresAreInRange(dictionary):
for square in dictionary:
try:
if int(square[:0]) <= 8 and \
pieces[-1] <= 'h':
return True
else:
return False
except ValueError:
return False
can be turned into
def allSquaresAreInRange(dictionary):
try:
return all(
(1 <= int(row) <= 8) and ('a' <= col <= 'h')
for (row, col) in dictionary
)
except ValueError:
return False
Here we make use of a few things:
As before, we use all(), and as before, we use a comprehension. But this time, we iterate through dictionary directly
Iterating through a dict is functionally identical to iterating through dict.keys(). So, we're iterating through the keys '8h', '2c', ...
Each key is a two-character string. Strings are iterable, just like lists are, and most iterables have an interesting property called "multiple assignment": if we assign exactly as many variables as the iterable has elements, then those elements get split up.
(row, col) = '8h', for example, is functionally identical to row = '8h'[0] and col = '8h'[1]. In both cases, we're left with row = '8' and col = 'h'.
This produces a ValueError if the number of elements on either side is mismatched - for example, if the key has only one character, or only three characters. A byproduct of this is that row and col are guaranteed to be exactly one-character long strings, if that error doesn't happen.
Our condition checks if the row is between 1 and 8, and whether the col is between A and H, using greater than/less than signs. This returns True or False, once again.
As you seemed to discover, using int() on something that doesn't represent an integer will also throw a ValueError.
This new snippet keeps the try/except blocks you came up with in yours, because they work just fine.
Python has a bit of a culture surrounding it that prides 'efficiently-written' code. Which is to say, code that looks as fancy as possible, and follows Functional Programming paradigms. Comprehensions, as well as all() and any(), are a big part of that, and so they're probably the 'correct' solution for any problem which they are a solution for (if they can be written concisely).
Similarly, the snippet
if condition:
return True
else:
return False
can almost always be condensed to
return condition
(or return bool(condition), in the case that condition deals with a value that has truthiness but isn't a boolean, such as None or an empty list or string). If this is applicable, it's good practice (but again, it's not always applicable).
The most important thing, though, is that your code works the way you want it to, and that it's clear enough for you to come back to it a few months down the line and figure out what you were doing, and why you were doing it that way. There are some cases where things can be written as comprehensions but that makes them extremely complicated and unreadable - and in those cases, it's sometimes a good idea to not write them as comprehensions, and do it the more verbose way. Just keep that in mind as you're continuing to develop, and you'll do fine.

Python List Creation Difference

I am trying to create a recursive function to sort the list from low to high.
Following code doesn't work
less = []
greater = []
def quicksort(array):
if len(array)<2:
return array
else:
pivot = array[0]
for i in array[1:]:
if i <= pivot:
less.append(i)
else:
greater.append(i)
return quicksort(less)+[pivot]+quicksort(greater)
print(quicksort([1,3,2,7,8]))
but I use a book code , it works. Would you advise me why?
def quicksort(array):
if len(array)<2:
return array
else:
pivot = array[0]
less = [i for i in array[1:] if i <= pivot]
greater = [i for i in array[1:] if i > pivot]
return quicksort(less)+[pivot]+quicksort(greater)
print(quicksort([1,3,2,7,8]))
You're using global less and greater lists, so you're going to end up building up the lists bigger and bigger and bigger, repeating your inputs many times (roughly proportional to the number of times you recursively call quicksort). less and greater keep growing until you blow the stack depth limit or run out of memory and Python dies to protect you from yourself.
Worse, you preserve state across calls, so the second and subsequent things you quicksort ends up including garbage from the prior sort operations, even if they're on inputs so short you could "sort" them trivially. Your code would work if you made less/greater local, initializing them afresh in each call:
def quicksort(array):
if len(array)<2:
return array
else:
pivot = array[0]
less = [] # Local!
greater = [] # Local!
for i in array[1:]:
if i <= pivot:
less.append(i)
else:
greater.append(i)
return quicksort(less)+[pivot]+quicksort(greater)

Return False if the same input is given more than once

I want to return False if the same input is given:
first_answer = input("select square number 1: ")
second_answer = input("select square number 2: ")
third_answer = input("select square number 3: ")
if first_answer == second_answer or first_answer == third_answer or
second_answer == first_answer or second_answer == third_answer or
third_answer == first_answer or third_answer == second_answer:
print("don\'t repeat squares")
Is there an easier way?
Do you like this:
set_answers = set()
set_answers.add(input("select square number 1: "))
set_answers.add(input("select square number 2: "))
set_answers.add(input("select square number 3: "))
if len(set_answers) < 3:
print("don\'t repeat squares")
?
The TRICK: set() stores only unique elements, so adding same value again to a set doesn't change the number of its elements.
Try this.
count = 3
answers = []
for i in range(0, count):
answers[i] = input("select square number " + str(i+1) + ": "
for i in range(0, count-1):
for j in range(i+1, count):
if answers[i] == answers[j]:
print("don\'t repeat squares")
It is (almost) always easier to abstract this kind of thing by using loops and arrays (or sets, or tuples) than to program each variable by hand.
answers is a list here, and the first loop inputs the data into the array. Note that you can easily change the amount of data you want simply by modifying the initial value of count -- this will change everything else as well (including the input messages!).
The second loop is actually a nested pair of for loops in order to generate all of the (relevant) pairs of data items to compare. Note that the first loop stops one short of the last element and that the second loop starts one after whatever the value of the first loop is. This is in order to avoid incorrectly comparing an element with itself.
CLARIFICATION:
[] is an empty list. A list in Python is just an ordered list of elements that can be accessed by their position (index) in the list. Indexes start from 0. (there are good reasons for this)
In general, the range function returns all the integers in the given range that includes the lower bound (the left argument) and does not include the upper bound (the right argument). (there are good reasons for this too)

recursion not stopping with 'if'

I am trying to write a code which prints True if given string has at max 2 consecutive c, and at max 1 b. I am using recursion to reduce the string and check that at max 'c' is present in the same index twice.But my recursion is not stopping till it empties the whole list. Can you please suggest what's wrong with my code. Thanks!
def stringcond(N,count=0,k=0):
N=list(N)
if(N.count('b')>1):
return False
if len(N)<2:
return True
else:
for i,j in enumerate(N):
if(j=='c'):
del N[i]
count+=1
if(k==i and count>2):
return False
stringcond(N,count=count,k=i)
return True
You have several mistakes. First, why are you splitting the characters into a list? There is a perfectly good count method for strings.
Your recursion fails because you ignore the return value. You would want something like
if not stringcond(N,count=count,k=i):
return False
# I make no claim that this logic is correct.
In any case, there is no need to recur. Use count to check the quantity of "b" and many-'c' substrings:
def stringcond(s, c_max=0):
return s.count('b') <= 1 and \
s.count("c" * (c_max+1)) == 0
You have to use the result of the stringcond call. Now your function will only return whatever was determined on the top level call.

Python - Create a recursion function

my question is basically this: Create a recursion function that takes a nested list as a
parameter and returns the sub-list that has minimum difference between its maximum and minimum elements.
For example: Function should return [1,2] for input [[1,199,59],[1,2],[3,8]]
I searched Google and stackoverflow, but i could not find this specific example.
What i would like to get help is with iteration. I want to, using recursion, iterate over each sub-list(can be as many as possible). I have achieved this with a for loop, but i cannot grasp the idea of iteration by using recursion method.
So far, i have this:
def sublist(mylist):
if len(mylist) == 0:
return []
elif len(mylist) == 1:
return mylist
else:
a = (mylist[0][0]) - (mylist[0][-1])
if a < sublist(mylist[1:]):
return mylist[0]
sublist([[1,199,58],[1,2],[3,8]])
This part, ( sublist(mylist[1:]) ) i know is clearly wrong. I'm trying to compare the value a, with the values from the mylist[1:]. I would appreciate much advice here.
Updated:
def differences(mylist):
diff = max(mylist) - min(mylist)
return diff
def sublist(nestedlist):
if len(nestedlist) == 1:
return nestedlist[0]
else:
if differences(nestedlist[0]) < differences(sublist(nestedlist[1:])):
return nestedlist[0]
else:
return sublist(nestedlist[1:])
print(sublist([[1,199,59],[1,2],[3,8]]))
i am assuming that you want to use recursion for the first level of the list. So, without giving you the code 100%, you have to do something like that:
1) create a method e.g diferences(list) that calculates the differences of a list and returns a list with the parameter list and the min difference i.e differences([1,2]) should return [1, [1,2]]. call it once on the first sublist i.e min = differences(mylist[0])
2) create your sublist method like this:
def sublist(initial_list):
# 1) call differences() method for the first sublist of the 'initial_list'
# 2) update 'min' with differences(initial_list[0])if differences(inilitial_list[0])[0] < min[0];
# 3) call sublist() again now removing the sublist you checked before from the arguement
# 4) (the following should be at the start of your sublist() method)
if len(initial_list) = 1:
if differences(initial_list) < min:
return initial_list
else: return min[1]
Hope that helps

Resources