How to rank tuple value in nested dictionary - python

I am trying to make a function that accepts a database and a year and it calculates the ranking of the names based on their count and then updates the database.
database = {('Spot','DOG'): {2013: (612, 1), 2014: (598, 3)},
('Princess','CAT'): {2013: (713, 2)},
('Smokey', 'CAT'): {2013: (523, 1), 2014: (514, 1)},
('Fido', 'DOG'): {2013: (558, 2), 2014: (655, 1)},
('Sparky','DOG'): {2104: (572, 2)}}
I have to rank the cats and dogs separately with the most popular name being rank 1, so descending order.
I'm only allowed to use basic expressions and statements, len, range, enumerate, int, get, items, keys, values, pop, copy, popitem, update, append, insert, extend,min, max, index, split, join, replace, sorted, sort, reversed, reverse, sets and basic expressions and statements and I can write my own functions and use them.
I can't import modules or use lambda or any thing besides whats on the allowed list. That is why I am stuck. This is my first programming class. I have no idea how to sort the tuple. I know how to sort a nested dictionary, there was a great post on here for that, but I am stuck at this tuple. Could you please help.
def rank_names_for_one_year(db, year):
list = []
list_2 = []
for k in db:
if 'MALE' in k:
for key in db[k]:
if year == key:
for n in db[k][year]:
list.append(n)
break
if 'FEMALE' in k:
for key in db[k]:
if year == key:
for n in db[k][year]:
list_2.append(n)
break
list.sort()
new_list = [()]
list_2.sort()
new_list_2 = [()]
for k in db:
if 'MALE' in k:
for i in range(len(list)):
new_list.append((list[i],i+1))
for key in db[k]:
if year == key:
for n in db[k][year]:
for i in range(len(new_list)):
for j in range(len(new_list[i])):
if new_list[i][j] == n:
db[k][year] = new_list[i]
if 'FEMALE' in k:
for i in range(len(list_2)):
new_list_2.append((list_2[i],i+1))
for key in db[k]:
if year == key:
for n in db[k][year]:
for i in range(len(new_list_2)):
for j in range(len(new_list_2[i])):
if new_list_2[i][j] == n:
db[k][year] = new_list_2[i]

database = {('TEST','DOG'):{2013:(612,1), 2014:(598,3)}, ('Spot','DOG'):{2013:(612,1), 2014:(598,3)},('Princess','CAT'):{2013:(713,2)},
('Princess1','CAT'):{2013:(713,2)},('Smokey', 'CAT'):{2013:(523,1), 2014:(514,1)},('Smokey1', 'CAT'):{2013:(523,1), 2014:(514,1)},('Fido', 'DOG'):{2013:(558, 2), 2014:(655, 1)},('Sparky','DOG'):{2104:(572,2)}}
def rank_names_for_one_year(db, year):
temp = {'DOG' : [], 'CAT' : []}
for k, v in db.items():
if year not in v:
continue
temp[k[1]].append((v[year][0], k[0]))
for animal_type, v in temp.items():
rank = 0
countPrev = -1
for i, (count, name) in enumerate(reversed(sorted(v))):
if countPrev != count:
rank = i + 1
countPrev = count
db[(name, animal_type)][year] = (count, rank)
rank_names_for_one_year(database, 2013)

Related

Python Shell Not Returning Anything

This is my code below that I believe should be working. When I call it, the python shell returns empty(blank) and just another Restart line pops up above. Wondering how to fix this?
Instructions for this function problem are the following:
Description: Write a function called animal_locator that takes in a dictionary
containing zoo locations as keys and their values being a list of tuples with the
specific animal and the population of that specific animal at that zoo. You should
return a dictionary containing the animals as keys and their values being a tuple
with their first element being an ordered list of all the zoo locations based on
how many animals are at each location (greatest to least) and the second element
being an integer of the total population of that specific animal.
You do not have to take in account case sensitivity.
def animal_locator(places):
newdict = {}
for city in places:
numtup = len(places[city])
num = 0
while num < numtup:
if places[city][num][0] not in newdict:
newlist = []
newtup = (places[city][num][1], city)
newlist.append(newtup)
for city1 in places:
if city1 != city:
for tup in places[city1]:
if tup[0] == places[city][num][0]:
tupnew = (tup[1], city1)
newlist.append(tupnew)
newlist.sort(reverse=True)
count = 0
newlist2 = []
for tup in newlist:
newlist2.append(tup[1])
count += tup[0]
newtup = (newlist2, count)
newdict[places[city][num][0]] = newtup
num += 1
return newdict
zoo_location1 = {'San Diego': [('lion', 4), ('tiger', 2), ('bear', 8)], 'Bronx': [('lion', 20), ('snake', 5), ('tiger', 1)], 'Atlanta': [('lion', 3), ('snake', 2), ('bee', 4500)], 'Orlando': [('bee', 234), ('tiger', 123)]}
animal_dict1 = animal_locator(zoo_location1)
print(animal_dict1)
I found out my num += 1 line needed to be indented by one tab and then it ran normally.

Check if a list of items is sorted according to 2 attributes

I have a list of objects that contains different attributes, like name and index. I have to write a function that check if the index value is given in alphabetical order.
i.e.
items = [item3, item1, item2]
# item1.name = arc; item1.index = 12
# item2.name = banana; item2.index = 27
# item3.name = cards; item3.index = 29
checkAlphaOrder(items) # If index corresponds to alphabetical order, returns True
This is embarrasing, but I can't find a simple way to do so.
You need
all(items[i].name <= items[i + 1].name and items[i].index <= items[i + 1].index
for i in range(len(items) - 1))
It would compare the name and index values of each consecutive pairs of elements. If each pair appear in ascending order of name and index, the whole list must be sorted.
One idea is to sort your list of objects by name. Then check index attributes are consistent via all and a generator comprehension:
class MyClass():
def __init__(self, name, index):
self.name = name
self.index = index
items = [MyClass('arc', 12), MyClass('banana', 27), MyClass('cards', 29)]
name_sorted = sorted(items, key=lambda x: x.name)
validate_res = all(i.index < j.index for i, j in zip(name_sorted, name_sorted[1:]))
#DeepSpace answer is the best so far.
return sorted(items, key=lambda x: x.name) == sorted(items, key=lambda x: x.index)

finding the maxaverage from given list of tuples

Write a Python function maxaverage(l) that takes a list of pairs of the form (name,score) as argument, where name is a string and score is an integer. Each pair is to be interpreted as the score of the named player. For instance, an input of the form [('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)] represents two scores of 73 and 7 for Kohli, two scores of 33 and 90 for Ashwin and one score of 122 for Pujara. Your function should compute the players who have the highest average score (average = total across all scores for that player divided by number of entries) and return the list of names of these players as a list, sorted in alphabetical order. If there is a single player, the list will contain a single name.
For instance, maxaverage([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)]) should return ['Pujara'] because the average score of Kolhi is 40 (80 divided by 2), of Ashwin is 61.5 (123 divided by 2) and of Pujara is 122 (122 divided by 1), of which 122 is the highest.
In the same way the solution should be ['Kohli', 'Ashwin'] if l = ([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara'‌​,22),('Ashwin',47)]) but I'm getting only kohli
from collections import defaultdict
def maxaverage(l):
dl = []
data_dict = defaultdict(list)
for k, v in l:
data_dict[k].append(v)
data_dict = dict(data_dict)
for k, v in data_dict.items():
data_dict[k] = sum(v) / len(v)
list(zip(data_dict.keys(), data_dict.values()))
max(data_dict.values())
x = (max(data_dict, key=data_dict.get))
dl.append(x)
return dl
Just add a list comprehension at the end of the method to get the keys of dict based on max average i.e
from collections import defaultdict
def maxaverage(l):
data_dict = defaultdict(list)
for k, v in l:
data_dict[k].append(v)
data_dict = dict(data_dict)
for k, v in data_dict.items():
data_dict[k] = sum(v) / len(v)
dl = [i for i,j in data_dict.items() if j == max(data_dict.values())]
return dl
Output:
maxaverage([('Kohli', 73), ('Ashwin', 33), ('Kohli', 7), ('Pujara', 22), ('Ashwin', 47)])
#['Ashwin', 'Kohli']
maxaverage(([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)])
#['Pujara']
Here is a corrected version of your code that ensures that the final result is sorted alphabetically. It also has some efficiency improvements:
from collections import defaultdict
def maxaverage(l):
data_dict = defaultdict(list)
for k, v in l:
data_dict[k].append(v)
data_dict = {k: sum(v)/len(v) for k,v in data_dict.items()}
max_avg = max(data_dict.values())
return sorted([k for k in data_dict if data_dict[k] == max_avg])
>>> maxaverage(([('Kohli',73),('Ashwin',33),('Kohli',7),('Pujara',122),('Ashwin',90)]))
['Pujara']
>>> maxaverage([('Kohli', 73), ('Ashwin', 33), ('Kohli', 7), ('Pujara', 22), ('Ashwin', 47)])
['Ashwin', 'Kohli']
Note that the solution in the 2nd test case should be ['Ashwin', 'Kohli'], not ['Kohli', 'Ashwin'] (as stated in your question) because the final list should be sorted.
Try these codes:
l = [('Kohli', 73), ('Ashwin', 33), ('Kohli', 7), ('Pujara', 22), ('Ashwin', 47)]
def max_average(l):
from operator import itemgetter
from itertools import groupby
lst_of_pairs = list()
for key, group in groupby(sorted(l, key=itemgetter(0)), key=itemgetter(0)):
scores = list(x[1] for x in group)
avg = sum(scores) / len(scores)
lst_of_pairs.append((key, avg))
lst_of_pairs.sort(key=itemgetter(1), reverse=True)
max_avg = lst_of_pairs[0][1]
return list(e[0] for e in filter(lambda x: x[1] == max_avg, lst_of_pairs))
print(max_average(l))
And for the case in 'l', you can get ['Ashwin', 'Kohli'] as expected. Remeber that the groupby will only work on a sorted lists.

In Python, How can I get the next and previous key:value of a particular key in a dictionary?

Okay, so this is a little hard to explain, but here goes:
I have a dictionary, which I'm adding content to. The content is a hashed username (key) with an IP address (value).
I was putting the hashes into an order by running them against base 16, and then using Collection.orderedDict.
So, the dictionary looked a little like this:
d = {'1234': '8.8.8.8', '2345':'0.0.0.0', '3213':'4.4.4.4', '4523':'1.1.1.1', '7654':'1.3.3.7', '9999':'127.0.0.1'}
What I needed was a mechanism that would allow me to pick one of those keys, and get the key/value item one higher and one lower. So, for example, If I were to pick 2345, the code would return the key:value combinations '1234:8.8.8.8' and '3213:4.4.4.4'
So, something like:
for i in d:
while i < len(d)
if i == '2345':
print i.nextItem
print i.previousItem
break()
Edit: OP now states that they are using OrderedDicts but the use case still requires this sort of approach.
Since dicts are not ordered you cannot directly do this. From your example, you are trying to reference the item like you would use a linked list.
A quick solution would be instead to extract the keys and sort them then iterate over that list:
keyList=sorted(d.keys())
for i,v in enumerate(keyList):
if v=='eeee':
print d[keyList[i+1]]
print d[keyList[i-1]]
The keyList holds the order of your items and you have to go back to it to find out what the next/previous key is to get the next/previous value. You also have to check for i+1 being greater than the list length and i-1 being less than 0.
You can use an OrderedDict similarly but I believe that you still have to do the above with a separate list as OrderedDict doesn't have next/prev methods.
As seen in the OrderedDict source code,
if you have a key and you want to find the next and prev in O(1) here's how you do that.
>>> from collections import OrderedDict
>>> d = OrderedDict([('aaaa', 'a',), ('bbbb', 'b'), ('cccc', 'c'), ('dddd', 'd'), ('eeee', 'e'), ('ffff', 'f')])
>>> i = 'eeee'
>>> link_prev, link_next, key = d._OrderedDict__map['eeee']
>>> print 'nextKey: ', link_next[2], 'prevKey: ', link_prev[2]
nextKey: ffff prevKey: dddd
This will give you next and prev by insertion order. If you add items in random order then just keep track of your items in sorted order.
You could also use the list.index() method.
This function is more generic (you can check positions +n and -n), it will catch attempts at searching a key that's not in the dict, and it will also return None if there's nothing before of after the key:
def keyshift(dictionary, key, diff):
if key in dictionary:
token = object()
keys = [token]*(diff*-1) + sorted(dictionary) + [token]*diff
newkey = keys[keys.index(key)+diff]
if newkey is token:
print None
else:
print {newkey: dictionary[newkey]}
else:
print 'Key not found'
keyshift(d, 'bbbb', -1)
keyshift(d, 'eeee', +1)
Try:
pos = 0
d = {'aaaa': 'a', 'bbbb':'b', 'cccc':'c', 'dddd':'d', 'eeee':'e', 'ffff':'f'}
for i in d:
pos+=1
if i == 'eeee':
listForm = list(d.values())
print(listForm[pos-1])
print(listForm[pos+1])
As in #AdamKerz's answer enumerate seems pythonic, but if you are a beginner this code might help you understand it in an easy way.
And I think its faster + smaller compared to sorting followed by building list & then enumerating
You could use a generic function, based on iterators, to get a moving window (taken from this question):
import itertools
def window(iterable, n=3):
it = iter(iterable)
result = tuple(itertools.islice(it, n))
if len(result) == n:
yield result
for element in it:
result = result[1:] + (element,)
yield result
l = range(8)
for i in window(l, 3):
print i
Using the above function with OrderedDict.items() will give you three (key, value) pairs, in order:
d = collections.OrderedDict(...)
for p_item, item, n_item in window(d.items()):
p_key, p_value = p_item
key, value = item
# Or, if you don't care about the next value:
n_key, _ = n_item
Of course using this function the first and last values will never be in the middle position (although this should not be difficult to do with some adaptation).
I think the biggest advantage is that it does not require table lookups in the previous and next keys, and also that it is generic and works with any iterable.
Maybe it is an overkill, but you can keep Track of the Keys inserted with a Helper Class and according to that list, you can retrieve the Key for Previous or Next. Just don't forget to check for border conditions, if the objects is already first or last element. This way, you will not need to always resort the ordered list or search for the element.
from collections import OrderedDict
class Helper(object):
"""Helper Class for Keeping track of Insert Order"""
def __init__(self, arg):
super(Helper, self).__init__()
dictContainer = dict()
ordering = list()
#staticmethod
def addItem(dictItem):
for key,value in dictItem.iteritems():
print key,value
Helper.ordering.append(key)
Helper.dictContainer[key] = value
#staticmethod
def getPrevious(key):
index = (Helper.ordering.index(key)-1)
return Helper.dictContainer[Helper.ordering[index]]
#Your unordered dictionary
d = {'aaaa': 'a', 'bbbb':'b', 'cccc':'c', 'dddd':'d', 'eeee':'e', 'ffff':'f'}
#Create Order over keys
ordered = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
#Push your ordered list to your Helper class
Helper.addItem(ordered)
#Get Previous of
print Helper.getPrevious('eeee')
>>> d
You can store the keys and values in temp variable in prior, and can access previous and next key,value pair using index.
It is pretty dynamic, will work for any key you query. Please check this code :
d = {'1234': '8.8.8.8', '2345':'0.0.0.0', '3213':'4.4.4.4', '4523':'1.1.1.1', '7654':'1.3.3.7', '9999':'127.0.0.1'}
ch = raw_input('Pleasure Enter your choice : ')
keys = d.keys()
values = d.values()
#print keys, values
for k,v in d.iteritems():
if k == ch:
ind = d.keys().index(k)
print keys[ind-1], ':',values[ind-1]
print keys[ind+1], ':',values[ind+1]
I think this is a nice Pythonic way of resolving your problem using a lambda and list comprehension, although it may not be optimal in execution time:
import collections
x = collections.OrderedDict([('a','v1'),('b','v2'),('c','v3'),('d','v4')])
previousItem = lambda currentKey, thisOrderedDict : [
list( thisOrderedDict.items() )[ z - 1 ] if (z != 0) else None
for z in range( len( thisOrderedDict.items() ) )
if (list( thisOrderedDict.keys() )[ z ] == currentKey) ][ 0 ]
nextItem = lambda currentKey, thisOrderedDict : [
list( thisOrderedDict.items() )[ z + 1 ] if (z != (len( thisOrderedDict.items() ) - 1)) else None
for z in range( len( thisOrderedDict.items() ) )
if (list( thisOrderedDict.keys() )[ z ] == currentKey) ][ 0 ]
assert previousItem('c', x) == ('b', 'v2')
assert nextItem('c', x) == ('d', 'v4')
assert previousItem('a', x) is None
assert nextItem('d',x) is None
Another way that seems simple and straight forward: this function returns the key which is offset positions away from k
def get_shifted_key(d:dict, k:str, offset:int) -> str:
l = list(d.keys())
if k in l:
i = l.index(k) + offset
if 0 <= i < len(l):
return l[i]
return None
i know how to get next key:value of a particular key in a dictionary:
flag = 0
for k, v in dic.items():
if flag == 0:
code...
flag += 1
continue
code...{next key and value in for}
if correct :
d = { "a": 1, "b":2, "c":3 }
l = list( d.keys() ) # make a list of the keys
k = "b" # the actual key
i = l.index( k ) # get index of the actual key
for the next :
i = i+1 if i+1 < len( l ) else 0 # select next index or restart 0
n = l [ i ]
d [ n ]
for the previous :
i = i-1 if i-1 >= 0 else len( l ) -1 # select previous index or go end
p = l [ i ]
d [ p ]

Insert an item into sorted list in Python

I'm creating a class where one of the methods inserts a new item into the sorted list. The item is inserted in the corrected (sorted) position in the sorted list. I'm not allowed to use any built-in list functions or methods other than [], [:], +, and len though. This is the part that's really confusing to me.
What would be the best way in going about this?
Use the insort function of the bisect module:
import bisect
a = [1, 2, 4, 5]
bisect.insort(a, 3)
print(a)
Output
[1, 2, 3, 4, 5]
Hint 1: You might want to study the Python code in the bisect module.
Hint 2: Slicing can be used for list insertion:
>>> s = ['a', 'b', 'd', 'e']
>>> s[2:2] = ['c']
>>> s
['a', 'b', 'c', 'd', 'e']
You should use the bisect module. Also, the list needs to be sorted before using bisect.insort_left
It's a pretty big difference.
>>> l = [0, 2, 4, 5, 9]
>>> bisect.insort_left(l,8)
>>> l
[0, 2, 4, 5, 8, 9]
timeit.timeit("l.append(8); l = sorted(l)",setup="l = [4,2,0,9,5]; import bisect; l = sorted(l)",number=10000)
1.2235019207000732
timeit.timeit("bisect.insort_left(l,8)",setup="l = [4,2,0,9,5]; import bisect; l=sorted(l)",number=10000)
0.041441917419433594
I'm learning Algorithm right now, so i wonder how bisect module writes.
Here is the code from bisect module about inserting an item into sorted list, which uses dichotomy:
def insort_right(a, x, lo=0, hi=None):
"""Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the right of the rightmost x.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]:
hi = mid
else:
lo = mid+1
a.insert(lo, x)
If there are no artificial restrictions, bisect.insort() should be used as described by stanga. However, as Velda mentioned in a comment, most real-world problems go beyond sorting pure numbers.
Fortunately, as commented by drakenation, the solution applies to any comparable objects. For example, bisect.insort() also works with a custom dataclass that implements __lt__():
from bisect import insort
#dataclass
class Person:
first_name: str
last_name: str
age: int
def __lt__(self, other):
return self.age < other.age
persons = []
insort(persons, Person('John', 'Doe', 30))
insort(persons, Person('Jane', 'Doe', 28))
insort(persons, Person('Santa', 'Claus', 1750))
# [Person(first_name='Jane', last_name='Doe', age=28), Person(first_name='John', last_name='Doe', age=30), Person(first_name='Santa', last_name='Claus', age=1750)]
However, in the case of tuples, it would be desirable to sort by an arbitrary key. By default, tuples are sorted by their first item (first name), then by the next item (last name), and so on.
As a solution you can manage an additional list of keys:
from bisect import bisect
persons = []
ages = []
def insert_person(person):
age = person[2]
i = bisect(ages, age)
persons.insert(i, person)
ages.insert(i, age)
insert_person(('John', 'Doe', 30))
insert_person(('Jane', 'Doe', 28))
insert_person(('Santa', 'Claus', 1750))
Official solution: The documentation of bisect.insort() refers to a recipe how to use the function to implement this functionality in a custom class SortedCollection, so that it can be used as follows:
>>> s = SortedCollection(key=itemgetter(2))
>>> for record in [
... ('roger', 'young', 30),
... ('angela', 'jones', 28),
... ('bill', 'smith', 22),
... ('david', 'thomas', 32)]:
... s.insert(record)
>>> pprint(list(s)) # show records sorted by age
[('bill', 'smith', 22),
('angela', 'jones', 28),
('roger', 'young', 30),
('david', 'thomas', 32)]
Following is the relevant extract of the class required to make the example work. Basically, the SortedCollection manages an additional list of keys in parallel to the items list to find out where to insert the new tuple (and its key).
from bisect import bisect_left
class SortedCollection(object):
def __init__(self, iterable=(), key=None):
self._given_key = key
key = (lambda x: x) if key is None else key
decorated = sorted((key(item), item) for item in iterable)
self._keys = [k for k, item in decorated]
self._items = [item for k, item in decorated]
self._key = key
def __getitem__(self, i):
return self._items[i]
def __iter__(self):
return iter(self._items)
def insert(self, item):
'Insert a new item. If equal keys are found, add to the left'
k = self._key(item)
i = bisect_left(self._keys, k)
self._keys.insert(i, k)
self._items.insert(i, item)
Note that list.insert() as well as bisect.insort() have O(n) complexity. Thus, as commented by nz_21, manually iterating through the sorted list, looking for the right position, would be just as good in terms of complexity. In fact, simply sorting the array after inserting a new value will probably be fine, too, since Python's Timsort has a worst-case complexity of O(n log(n)). For completeness, however, note that a binary search tree (BST) would allow insertions in O(log(n)) time.
This is a possible solution for you:
a = [15, 12, 10]
b = sorted(a)
print b # --> b = [10, 12, 15]
c = 13
for i in range(len(b)):
if b[i] > c:
break
d = b[:i] + [c] + b[i:]
print d # --> d = [10, 12, 13, 15]
# function to insert a number in an sorted list
def pstatement(value_returned):
return print('new sorted list =', value_returned)
def insert(input, n):
print('input list = ', input)
print('number to insert = ', n)
print('range to iterate is =', len(input))
first = input[0]
print('first element =', first)
last = input[-1]
print('last element =', last)
if first > n:
list = [n] + input[:]
return pstatement(list)
elif last < n:
list = input[:] + [n]
return pstatement(list)
else:
for i in range(len(input)):
if input[i] > n:
break
list = input[:i] + [n] + input[i:]
return pstatement(list)
# Input values
listq = [2, 4, 5]
n = 1
insert(listq, n)
Well there are many ways to do this, here is a simple naive program to do the same using inbuilt Python function sorted()
def sorted_inserter():
list_in = []
n1 = int(input("How many items in the list : "))
for i in range (n1):
e1 = int(input("Enter numbers in list : "))
list_in.append(e1)
print("The input list is : ",list_in)
print("Any more items to be inserted ?")
n2 = int(input("How many more numbers to be added ? : "))
for j in range (n2):
e2= int(input("Add more numbers : "))
list_in.append(e2)
list_sorted=sorted(list_in)
print("The sorted list is: ",list_sorted)
sorted_inserter()
The output is
How many items in the list : 4
Enter numbers in list : 1
Enter numbers in list : 2
Enter numbers in list : 123
Enter numbers in list : 523
The input list is : [1, 2, 123, 523]
Any more items to be inserted ?
How many more numbers to be added ? : 1
Add more numbers : 9
The sorted list is: [1, 2, 9, 123, 523]
To add to the existing answers: When you want to insert an element into a list of tuples where the first element is comparable and the second is not you can use the key parameter of the bisect.insort function as follows:
import bisect
class B:
pass
a = [(1, B()), (2, B()), (3, B())]
bisect.insort(a, (3, B()), key=lambda x: x[0])
print(a)
Without the lambda function as the third parameter of the bisect.insort function the code would throw a TypeError as the function would try to compare the second element of a tuple as a tie breaker which isn't comparable by default.
This is the best way to append the list and insert values to sorted list:
a = [] num = int(input('How many numbers: ')) for n in range(num):
numbers = int(input('Enter values:'))
a.append(numbers)
b = sorted(a) print(b) c = int(input("enter value:")) for i in
range(len(b)):
if b[i] > c:
index = i
break d = b[:i] + [c] + b[i:] print(d)`

Categories