So I have this list below. I am doing an ip calculator and am currently doing supernetting. I currently have the ip's as binary in a list.
I want to get the common numbers in a list and add them to a new variable so that I'll have a new string with all the common ones etc like it should stop adding the common numbers to a string when the same index's of each binary number stop being the same. I can't figure out how to compare each one though? I tried for loops and everything and it doesn't behave as I want it to.
['11001101011001000000000000000000',
'11001101011001000000000100000000',
'11001101011001000000001000000000',
'11001101011001000000001100000000']
my output for this should be 11001101 . 01100100 . 000000
If I understand you correctly, you are looking for the longest common prefix of all the strings. There are probably more elegant and/or faster ways, but you could e.g. just zip the different strings and takewhile they are all the same, i.e. have only one element as a set.
>>> from itertools import takewhile
>>> lst = ['11001101011001000000000000000000',
... '11001101011001000000000100000000',
... '11001101011001000000001000000000',
... '11001101011001000000001100000000']
...
>>> ''.join(t[0] for t in takewhile(lambda t: len(set(t)) == 1, zip(*lst)))
'1100110101100100000000'
>>> '.'.join(_[i:i+8] for i in range(0, len(_), 8)) # just adding dots...
'11001101.01100100.000000'
Breaking this down a bit:
zip(*lst) iterates the "slices" through all the strings in the list, e.g. ('1', '1', '1', '1') for the first position
takewhile takes that sequence and -- as the name suggests -- takes elements as long as the given condition is true
lambda t: len(set(t)) == 1 is that condition, converting the slice through the strings to a set and checking whether that set has just one element; for ('0', '0', '1', '1'), the set will be {'0', '1'} and thus takewhile stops
''.join(t[0] for ...) joins the same elements back to a string; here, t[0] is just the first element of the tuple of same elements
the last line is just to add the . after 8 digits; here, _ is the result of the previous line
I want to ask a question about zip() in python.
Consider the following simple code to demonstrate zip().
a = ['1', '2', '3']
b = ['a', 'b', 'c']
for key, value in zip(a, b):
print(key + value)
I know that the following output is produced:
1a
2b
3c
where each element in the corresponding lists are concatenated.
As a beginner in Python3, I understand the following about zip():
zip() creates a zip object, related to OOP that can be shown using list():
my_zip = zip(a, b)
print(my_zip)
print(list(my_zip))
>>> <zip object at 0xsomelocation>
>>>[('1', 'a'), ('2', 'b'), ('3', 'c')]
such that the zip object is a list of tuples.
My confusion is in this line from the original block of code, which I don't really understand:
for key, value in zip(a, b)
My interpretation is that as we are looping through our zip object, which has some innate __next__() method called on by our for loop, we loop through each tuple in turn.
For our first iteration of the loop, we get:
('1', 'a')
and python assigns '1' and 'a' to our variables key and value respectively. This is repeated until the end of the list dimensions i.e. 3 times.
Is this the correct interpretation of what is happening in our code?
such that the zip object is a list of tuples.
zip() doesn't return a list of tuples. It returns an iterator of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables.
The iterator stops when the shortest input iterable is exhausted. With a single iterable argument, it returns an iterator of 1-tuples. With no arguments, it returns an empty iterator.
and python assigns '1' and 'a' to our variables key and value respectively. This is repeated until the end of the list dimensions i.e. 3 times.
Yes. Rest of your interpretation is correct.
BONUS:
zip() should only be used with unequal length inputs when you don’t care about trailing, unmatched values from the longer iterables. If those values are important, use itertools.zip_longest() instead.
1)
d=dict(input().split())
ValueError: dictionary update sequence element #0 has length 3; 2 is required
2)
n=int(input())
d = dict(input().split() for _ in range(n))
When you call dict() with an iterable it expects that iterable to return pairs of values, that it can use as keys and values to create the dict. So, these examples are all valid:
dict([('key', 'value'), ('other_key', 'other_value')])
dict(['ab', 'bc', 'dd']) # 'ab' is pretty much equivalent to a list ['a', 'b']
dict([['a', 1], ['b', 2]])
dict(['key value'.split(), 'other_key other_value'.split()])
So, number one would work if you input character pairs, like aa bb cc. It will not work for any other case.
Second one will make inputs iterable, which is pretty much the same as wrapping it in a list. It will work for any input value that can be split into a pair. These would be valid:
key value
other_key other_value
aa
These would be invalid (not pairs):
key value other_value
a
aaa
So it all depends on the input.
I have a list of 760 files, from which I extract 2 lines of data, which are then stored in a dictionary:
output = {'file number':data, '1':somedatain1, '2':somedatain2, ... '760':somedatain760}
N.B.
The numbers are strings because they have been obtained by doing an os.listdir('.') in order to get a list of the filenames and splitting the string down. [I could convert this into an integer number (using int()) if needed]
The dictionary is then printed by creating a list of the keys and iterating:
keys = output.keys()
for x in keys:
print(x, '\t', output[x])
However the output is in a random order [because of the unordered nature of a dictionary, which is, I believe, an inherent property - although I don't know why this is] and it would be far more convenient if the output was in numerical order according to the file number. This, then throws up the question:
Given that my list of keys is either
1.keys = ['filename', '2', '555', '764' ... '10']
or, if i change the string of the file number to an integer:
2.keys = ['filename', 2, 555, 764 ... 10]
how do i sort my list of keys according to the numeric value of the file number if it is strings (as shown in 1. above), or if it is of mixed object types (i.e. 1 string and 760 integers as shown in 2 above)?
You can give the sorted() function a key:
sorted(output, key=lambda k: int(k) if k.isdigit() else float('-inf'))
This will sort strings before numbers, however. Note that there is no need to call dict.keys(); iteration over a dictionary already yields a sequence of keys, just call sorted() directly on the dictionary.
Python 3 does not define ordering for strings when compared with numbers, so for any key that is not a digit, float('-inf') (negative infinity) is returned instead to at least put those keys at the start of the ordering.
Demo:
>>> sorted(keys, key=lambda k: int(k) if k.isdigit() else float('-inf'))
['filename', '2', '10', '555', '764']
Just add your list to another variable and then following statement you get correct output:
listofdict = [{'key': value1,'key': value2,.......}]
output = listofdict[::-1]
print(output)
I come from OOP background and trying to learn python.
I am using the max function which uses a lambda expression to return the instance of type Player having maximum totalScore among the list players.
def winner():
w = max(players, key=lambda p: p.totalScore)
The function correctly returns instance of type Player having maximum totalScore.
I am confused about the following three things:
How does the max function work? What are the arguments it is taking? I looked at the documentation but failed to understand.
What is use of the keyword key in max function? I know it is also used in context of sort function
Meaning of the lambda expression? How to read them? How do they work?
These are all very noobish conceptual questions but will help me understand the language. It would help if you could give examples to explain.
Thanks
lambda is an anonymous function, it is equivalent to:
def func(p):
return p.totalScore
Now max becomes:
max(players, key=func)
But as def statements are compound statements they can't be used where an expression is required, that's why sometimes lambda's are used.
Note that lambda is equivalent to what you'd put in a return statement of a def. Thus, you can't use statements inside a lambda, only expressions are allowed.
What does max do?
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item. With two or
more arguments, return the largest argument.
So, it simply returns the object that is the largest.
How does key work?
By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).
To modify the object before comparison, or to compare based on a particular attribute/index, you've to use the key argument.
Example 1:
A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.
>>> lis = ['1', '100', '111', '2']
Here max compares the items using their original values (strings are compared lexicographically so you'd get '2' as output) :
>>> max(lis)
'2'
To compare the items by their integer value use key with a simple lambda:
>>> max(lis, key=lambda x:int(x)) # compare `int` version of each item
'111'
Example 2: Applying max to a list of tuples.
>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]
By default max will compare the items by the first index. If the first index is the same then it'll compare the second index. As in my example, all items have a unique first index, so you'd get this as the answer:
>>> max(lis)
(4, 'e')
But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:
>>> max(lis, key = lambda x: x[1])
(-1, 'z')
Comparing items in an iterable that contains objects of different type:
List with mixed items:
lis = ['1','100','111','2', 2, 2.57]
In Python 2 it is possible to compare items of two different types:
>>> max(lis) # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x)) # compare integer version of each item
'111'
But in Python 3 you can't do that any more:
>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
max(lis)
TypeError: unorderable types: int() > str()
But this works, as we are comparing integer version of each object:
>>> max(lis, key=lambda x: int(x)) # or simply `max(lis, key=int)`
'111'
Strongly simplified version of max:
def max(items, key=lambda x: x):
current = item[0]
for item in items:
if key(item) > key(current):
current = item
return current
Regarding lambda:
>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5
>>> times_two = lambda x: 2*x
>>> times_two(2)
4
max function is used to get the maximum out of an iterable.
The iterators may be lists, tuples, dict objects, etc. Or even custom objects as in the example you provided.
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
So, the key=func basically allows us to pass an optional argument key to the function on whose basis is the given iterator/arguments are sorted & the maximum is returned.
lambda is a python keyword that acts as a pseudo function. So, when you pass player object to it, it will return player.totalScore. Thus, the iterable passed over to function max will sort according to the key totalScore of the player objects given to it & will return the player who has maximum totalScore.
If no key argument is provided, the maximum is returned according to default Python orderings.
Examples -
max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7
people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')
How does the max function work?
It looks for the "largest" item in an iterable. I'll assume that you
can look up what that is, but if not, it's something you can loop over,
i.e. a list or string.
What is use of the keyword key in max function? I know it is also used in context of sort function
Key is a lambda function that will tell max which objects in the iterable are larger than others. Say if you were sorting some object that you created yourself, and not something obvious, like integers.
Meaning of the lambda expression? How to read them? How do they work?
That's sort of a larger question. In simple terms, a lambda is a function you can pass around, and have other pieces of code use it. Take this for example:
def sum(a, b, f):
return (f(a) + f(b))
This takes two objects, a and b, and a function f.
It calls f() on each object, then adds them together. So look at this call:
>>> sum(2, 2, lambda a: a * 2)
8
sum() takes 2, and calls the lambda expression on it. So f(a) becomes 2 * 2, which becomes 4. It then does this for b, and adds the two together.
In not so simple terms, lambdas come from lambda calculus, which is the idea of a function that returns a function; a very cool math concept for expressing computation. You can read about that here, and then actually understand it here.
It's probably better to read about this a little more, as lambdas can be confusing, and it's not immediately obvious how useful they are. Check here.
According to the documentation:
max(iterable[, key]) max(arg1, arg2, *args[, key]) Return the
largest item in an iterable or the largest of two or more arguments.
If one positional argument is provided, iterable must be a non-empty
iterable (such as a non-empty string, tuple or list). The largest item
in the iterable is returned. If two or more positional arguments are
provided, the largest of the positional arguments is returned.
The optional key argument specifies a one-argument ordering function
like that used for list.sort(). The key argument, if supplied, must be
in keyword form (for example, max(a,b,c,key=func)).
What this is saying is that in your case, you are providing a list, in this case players. Then the max function will iterate over all the items in the list and compare them to each other to get a "maximum".
As you can imagine, with a complex object like a player determining its value for comparison is tricky, so you are given the key argument to determine how the max function will decide the value of each player. In this case, you are using a lambda function to say "for each p in players get p.totalscore and use that as his value for comparison".
max is built in function which takes first argument an iterable (like list or tuple)
keyword argument key has it's default value None but it accept function to evaluate, consider it as wrapper which evaluates iterable based on function
Consider this example dictionary:
d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}
Ex:
>>> max(d.keys())
'sword'
As you can see if you only pass the iterable without kwarg(a function to key) it is returning maximum value of key(alphabetically)
Ex.
Instead of finding max value of key alphabetically you might need to find max key by length of key:
>>>max(d.keys(), key=lambda x: len(x))
'artwork'
in this example lambda function is returning length of key which will be iterated hence while evaluating values instead of considering alphabetically it will keep track of max length of key and returns key which has max length
Ex.
>>> max(d.keys(), key=lambda x: d[x])
'friend'
in this example lambda function is returning value of corresponding dictionary key which has maximum value
Assuming that people who come to this page actually want to know what is key= inside len(), here is the simple answer:
len() counts the length of the object. If we specify len as a key function in min(), max(), it will return the smallest/largest item based on their length.
food = ['bread', 'tea', 'banana', 'kiwi', 'tomato']
print(max(food, key=len)) # banana
print(min(food, key=len)) # tea