Python sorting function - python

em...I feel confused about this code, I am really new to coding, and wonder anyone can help:
def takeSecond(elem):# If I pass the argument as a list, why don't I need to specify it here?
return elem[1] # what return elem[1] means,does it return the y in (x,y)? but why!?
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
random.sort(key=takeSecond) # key = takeSecond what is this even mean lol?..
print('Sorted list:', random)

Let's say you have a list of items, which contains:
list = [a,b,c]
If you use the following piece of code:
def func():
return list[1]
You'd get "b" as output. The number "1" is not the first element, it's the second element. The counting in python starts at 0. So basically, if you want to access "a", you have to use:
def func():
return list[0]
Because 0 = a, 1 = b, 2 = c, and so on. If you change return elem[1] to return elem[0] you get the variable x.

Here your trying to sort based on second value in given list
takeSecond function is always returns the second value in the given element.
In random.sort() method calling with your passing key parameter as takeSecond function, which means sorting perform based on that element it happen. In our case it will return second element. So sorting is perform based on second element
And then printing the sorted list

Related

Python - how to take the max length from a value of dictionary? Without lambda

Let us say I have this function:
def frequent_base(self):
dict = {}
for i in range(len(self.items)):
if self.items[i].base not in dict:
dict[self.items[i].base] = [(self.items[i].value)]
else:
dict[self.items[i].base] += [(self.items[i].base)]
return max(len(dict[self.items]), key=len(d))
Now, I can make it complicated and build a function which returns me index and such..
but it is bad coding and bad habit and takes long time ( especially in a test ).
How do I take the length?
let us say I have:
key1 with length 3 of value ( key1 has 3 values )
key2 with length 4 of value ( key 2 has 4 values )
key3 with length 2 of value ( key 3 has 2 values )
How do I take, not the key itself, not the value itself, but the len of values of key? which is 4 in this case.
or how do I take the key itself and then say length of value of that key? But I want to use Max function, I need to understand how to use that function good, with the key.
I will write and make myself super clear:
dict[1] = [1,2,3]
dict[2] = [1,2,3,4,5]
dict[3] = [1,2,3,7,8,9,10]
dict = {1: [1,2,3], 2:[1,2,3,4,5], 3:[1,2,3,7,8,9,10]}
I wish to return not dict[3], not 3, not the list of dict[3] it self.
I wish to return the length of the dict[3], which is 7
def frequent_base(self):
dict = {}
for i in range(len(self.items)):
if self.items[i].base not in dict:
dict[self.items[i].base] = [(self.items[i].value)]
else:
dict[self.items[i].base] += [(self.items[i].base)]
def key_for_len(dictionary):
return dictionary[1]
return max(dict.items(), key= key_for_len)
I am received error
Only thing you seem to need is maximal length amongst the values of your dictionary. You can easily get all the values using d.values() (d.items() would give you (key, value) tuples, which are harder to compare). Now we can easily calculate lengths of each value with generator comprehension (very much like list comprehension, which would also work) - len(v) for v in d.values(). Now we have an iterable with all the lengths, so it's just a matter of finding the maximum -
max(len(v) for v in d.values())
Should you need to get key or value with maximum length, we'd have to take a slightly different approach - we can use max key = argument to specify how we decide which element in the iterable is maximal - it is obvious when we are trying to get a maximum from few numbers, but not when we try to decide if (1, 3) is bigger than (2, 2) - in such case, we need to create a function that maps our items to easily comparable things like a number. In this case, we'd have tuples of (key, value) and we are comparing length of value - thus our function would be
def lenOfValue(kv):
return len(kv[1]) # kv[1] - 2nd element of a (key, value) tuple
code(1)
Then we pass that to max:
print(max(d.items(), key = lenOfValue))
And we get (2, [3, 4, 5, 6])
Bonus: lambda
Lambdas can be used here, which are really just a shorthand that lets us skip defining whole another function that we will probably never use again.
This code would be functionally exactly the same.
print(max(d.items(), key = lambda kv: len(kv[1])))
code(2)
Lambdas are nothing very complicated, being just a notation for creating simple, one-liner functions without all the bother of a def block, return etc.
Because Python's functions are objects like nearly anything else, this piece of code:
lenOfValue = lambda kv: len(kv[1])
really is in no way different that our previously used more lengthy definition of:
def lenOfValue(kv):
return len(kv[1])
It saves us few words and shows us the middle step between code(1) and code(2).
a_dict = {'some_key':[67,30,10], 'another_key':[87]}
max({ (k,len(v)) for k,v in a_dict.items() })
('some_key', 3)

In Python, can a loop be used within a function?

I am just learning python and was trying to define a function using a for loop.
The code is as follows -
def chk(hilist):
``` The function returns the output of the enumerate function as (x1,y1) (x2,y2)...
```
for item in enumerate(hilist):
return item
I ran the above function for the input 'string' as below -
abc = chk('string')
abc
The output came out as (0,s).
If I ran the regular for function and the output will be as follows -
(0, 's')
(1, 't')
(2, 'r')
(3, 'i')
(4, 'n')
(5, 'g')
Can someone please help me understand what I am doing wrong ?
Thanks in advance.
Return will break the function immediately.
So, you have to save the result in a list and return it:
def chk(hilist):
""" The function returns the output of the enumerate function as (x1,y1) (x2,y2)...
"""
ret_list=list()
for item in enumerate(hilist):
ret_list.append(item)
return ret_list
in Python (and in all programming languages), using the return keyword will get you out of the function, so I propose two solutions:
solution 1: store your tuples in a list and then return the list
itself
solution 2: replace return with yield (but if you want to print returned items convert it to a list ex: list(abc(some_arguments)))
I think the simplest solution would be to use print(item) if you wanna get all the enumerated values from 'string':
def chk(hilist):
for item in enumerate(hilist):
print(item)
This worked smoothly for me.

choosing a random number from a tuple + some numbers

I have a tuple of numbers, and I want to choose a random number from my tuple in addition with a certain number. For example:
my_tuple = (1,2,3)
and I have the number 4. I want to choose a random number from the numbers 1,2,3,4 (without changing the tuple of course).
I tried:
my_tp = (1, 2, 3)
a = random.choice(list(my_tp).append(4))
print(a)
I'm new to python. I tried converting the tuple to a list, and then performing the random function.
The code above didn't work. Got the error
object of type 'NoneType' has no len()
Would love some help.
list.append returns none
Once converting to a list as you have done, appending will modify that list but return none so that is the source of your error.
To get round that you can either convert the tuple to a list then append 4 to it, then use random.choice, or in just one step, you can concatenate a list of [4] with the + operand.
This approach is much simpler:
import random
my_tuple = (1,2,3)
random.choice(list(my_tuple) + [4])
Hope this helps and clears some things up! :)
Update:
If you want to just randomly select from the tuple without the last item, then just slice the list with the normal syntax:
random.choice(list(my_tuple)[:-1])
The method list.append alters the provided list and returns None, which explains the exception you got. To get the desired result, you can implicitly use the tuple.__add__ method, which will return a new tuple.
values = (1, 2, 3)
random.choice(values + (4,))
If you want to remove values in a concise-ish fashion, using a set might be appropriate.
values = {1, 2, 3}
random.choice(list(values - {3}))
You can try:
my_tuple = (1,2,3)
random.choice((*my_tuple, 4))
Where (*my_tuple, 4) creates a new tuple with the unpacked content of my_tuple and 4.

Trying to find majority element in a list

I'm writing a function to find a majority in a Python list.
Thinking that if I can write a hash function that can map every element to a single slot in the new array or to a unique identifier, perhaps for a dictionary, that should be the best and it should be undoable. I am not sure how to progress. My hash function is obviously useless, any tips on what I can/should do, or if this is even a reasonable approach?
def find_majority(k):
def hash_it(q):
return q
map_of = [0]*len(k)
for i in k:
mapped_to = hash_it(i) #hash function
map_of[mapped_to]+=1
find_majority([1,2,3,4,3,3,2,4,5,6,1,2,3,4,5,1,2,3,4,6,5])
Python has a built-in class called Counter that will do this for you.
>>> from collections import Counter
>>> c = Counter([1,2,3,4,3,3,2,4,5,6,1,2,3,4,5,1,2,3,4,6,5])
>>> c.most_common()
[(3, 5), (2, 4), (4, 4), (1, 3), (5, 3), (6, 2)]
>>> value, count = c.most_common()[0]
>>> print value
3
See the docs.
http://docs.python.org/2/library/collections.html#collections.Counter
There is an easy way to realize like this
l = [1,2,3,4,3,3,2,4,5,6,1,2,3,4,5,1,2,3,4,6,5]
print(max(set(l), key = l.count)) # 3
I think your approach is to use another array as big as k as your "hash map". If k is huge but the number of unique elements is not so huge, you would be wasting a lot of space. Furthermore, to find the majority, you would have to loop through your map_of hashmap/array to find the max.
On the other hand, a dictionary/set (where hashing is not your concern, and the underlying array structure will probably be more compact for average cases) seems a little more appropriate. Needless to say, with the occurring elements as keys and their occurrences as values, you can find what you want in one single iteration.
So, something like:
def find_majority(k):
myMap = {}
maximum = ( '', 0 ) # (occurring element, occurrences)
for n in k:
if n in myMap: myMap[n] += 1
else: myMap[n] = 1
# Keep track of maximum on the go
if myMap[n] > maximum[1]: maximum = (n,myMap[n])
return maximum
And as expected, we get what we want.
>>> find_majority([1,2,3,4,3,3,2,4,5,6,1,2,3,4,5,1,2,3,4,6,5])
(3, 5)
Of course, Counters and other cool modules will let you do what you want in finer syntax.

Reversing a nested tuple in Python using the function reversed

I have a tuple and would like to reverse it in Python.
The tuple looks like this : (2, (4, (1, (10, None)))).
I tried reversing in Python by:
a = (2, (4, (1, (10, None))))
b = reversed(a)
It returns me this:
<reversed object at 0x02C73270>
How do I get the reverse of a? Or must I write a function to do this?
The result should look like this:
((((None, 10), 1), 4), 2)
def my_reverser(x):
try:
x_ = x[::-1]
except TypeError:
return x
else:
return x if len(x) == 1 else tuple(my_reverser(e) for e in x_)
Try this deep-reverse function:
def deep_reverse(t):
return tuple(deep_reverse(x) if isinstance(x, tuple) else x
for x in reversed(t))
This will handle arbitrarily nested tuples, not just two-tuples.
As explained in the documentation, the reversed function returns an iterator (hence the <reversed at ...>). If you want to get a list or a tuple out of it, just use list(reversed(...)) or tuple(reversed(...)).
However, it's only part of our problem: you'll be reversing the initial object (2, (...)) as (...,2), while the ... stays the same. You have to implement a recursive reverse: if one element of your input tuple is an iterable, you need to reverse it to.
It does not make sense to do this with reversed, sorry. But a simple recursive function would return what you want:
def reversedLinkedTuple(t):
if t is None:
return t
a, b = t
return reversedLinkedTuple(b), a
reversed is usable only on reversible iterable objects like lists, tuples and the like. What you are using (a linked list) isn't iterable in the sense of the Python built-in iter.
You could write a wrapping class for your linked list which implements this and then offers a reverse iterator, but I think that would be overkill and would not really suit your needs.
def reverse(x):
while x >= 0:
print(x)
x = x = 1
reverse(x)

Categories