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
Related
The goal is: turn 3 lists of the same length into 2 lists, the length of which does not differ by more than 1, elements from different source lists must alternate and their order must not be violated. For example: if ‘A’ went before ' B’ in the source list, then ‘B’ cannot go before ‘A’ in the final list.
So, I decided to wrote a function:
def list_3_2(list1,list2,list3):
#split all lists in one list
a=sum((list(i) for i in zip(list1,list2,list3)),[])
#I want to separate list "a" to two new lists: l1 and l2
l1=[]
l2=[]
#//////
return(l1,l2)
list_3_2(['1','2','3'],['4','5','6'],['7','8','9'])
Then I faced the problem of separation. I found some similar issues, but their lists were structured differently, like main_list=['3 5', '1 2', '1 7']. I get the another result, after the unification: a=['1', '4', '7', '2', '5', '8', '3', '6', '9']. How could i separate this list?
Maybe I'm misunderstanding the question.
from itertools import chain
def list_3_2(l1, l2, l3):
x = list(chain.from_iterable(zip(l1, l2, l3)))
m = len(x) // 2
return (x[:m], x[m:])
Zip the lists, concatenate the resulting tuples into a single list, then split that in half.
Well, according to the finalizing information you shared, I believe you were extremely close to the solution, you just needed to split the final array. What do you think about this?
def list_3_2(list1,list2,list3):
a=sum((list(i) for i in zip(list1,list2,list3)),[])
return a[:len(a)//2], a[len(a)//2:]
print(list_3_2(['1','2','3'],['4','5','6'],['7','8','9']))
Basically, splitting the list into two parts, where one is at most 1 element larger than the other, corresponds to splitting an arbitrary list at the index of the rounded-down midpoint. The parts will be of different length iff the original array (chain of inputs) has odd length.
The midpoint index of an array is len(array)//2 - len(array) is the full length and //2 is the operation of "division in half rounded down".
Lastly, to split the array using this midpoint index, we use the splicing mechanism in python. The syntax is as follows:
a[:m] = all elements of a from index 0 (= the beginning) to index m-1.
a[m:] = all elements of a from index m to index len(a) - 1 (= the end).
Hey try that hope is that what you want
def list_3_2(list1,list2,list3):
#split all lists in one list
#I want to separate list "a" to two new lists: l1 and l2
a=[]
[a.extend(j) for j in (list(list(i) for i in zip(list1,list2,list3)))]
#//////
div=int(len(a)/2)
l1=a[0:div]
l2=a[div:]
return l1,l2
print(list_3_2(['1','2','3'],['4','5','6'],['7','8','9']))
I was trying to compare different lists and to get the shorter one among them with the min() built-in function (I know that this isn't what min() made for but I was just trying) and I've got some results that made me not sure what the output was based on
min(['1','0','l'], ['1', '2'])
>>> ['1', '0', 'l']
min(['1','2','3'], ['1', '2'])
>>> ['1', '2']
min(['1', '2'], ['4'])
>>> ['1', '2']
min(['1', 'a'], ['0'])
>>> ['0']
min(['1', 'a'], ['100000000'])
>>> ['1', 'a']
I don't know what is the output based on and I hope someone can help me and clarify this behavior.
The min() function takes the keyword argument key which you can use to specify what exact value to compare. It is a function which gets the list in your case as the argument.
So to get the shortest list, you can use this code:
min(['1','0','l'], ['1', '2'], key=lambda x: len(x))
Regarding your code and how the min() function determines the result:
You can look at your list like a string (which is just a list of characters in theory). If you'd compare a string to another one, you'd look at the letters from left to right and order them by their leftmost letters. For example abc < acb because b comes before c in the alphabet (and a=a so we can ignore the first letter).
With lists it's the same. It will go through the items from left to right and compare them until it finds the first one which is not equal in both lists. The smaller one of those is then used to determine the "smaller" list.
min finds the 'smallest' of the lists by the comparison operator they provide. For lists, it works by lexicographical order - of two lists, the one whose first unequal(to the elements in the other list at the same index) element is larger, is the larger list.
You can check what an inbuilt function does in the documentation
as you can see the minimum function accepts two things as its parameters:
min(iterable, *[, key, default]) : which is used to get the smallest value in an iterable object such as a list.
min(arg1, arg2, *args[, key]): which is what you are current using. It gets the minimum value when both arguments are compared. When comparing lists to see which one is smaller, it will get the first index that does not have the same value in both lists i.e.
a = [3,5,1]
b = [3,3,1]
result = a > b # true
here the first index that is not the same on both lists is index 1, and so the comparison is 5 > 3 (which is true)
using this logic of comparing lists, the min() function will return the list that has the smallest index which is unique and smaller than the other list.
See lexicographical order.
If you place characters, then we use lexicographical ordering, and so
>>> 'a' < 'b'
True
>>> '1' < '2'
True
>>> 'a' < 'A'
False
From the documentation:
Docstring:
min(iterable, *[, default=obj, key=func]) -> value
min(arg1, arg2, *args, *[, key=func]) -> value
With a single iterable argument, return its smallest item. The
default keyword-only argument specifies an object to return if
the provided iterable is empty.
With two or more arguments, return the smallest argument.
So, for example,
IN: min([5,4,3], [6])
OUT: [6]
As #Tim Woocker wrote, you should use a function(argument key) to specify what you want to compare.
For a given list with string digits, I want to return the different string numbers that can be generated using all the elements in the list (so if there are 5 elements, the number should consist of 5 digits).
The task is to return the possible permutations, the smallest permutation and the maximum permutation in a list.
answer should be converted to integers
If '0' is present in the input, it will produce string numbers with leading zeroes, this is not taken into account when they are converted to integers.
This is my code now:
from itertools import permutations
def proc_arr(arr):
lst = [] # define new list
list_of_tuples = list(permutations(arr, len(arr))) # now they are tuples in a list
# convert to integers in list
separator = [map(str,x) for x in list_of_tuples]
together = [int(''.join(s)) for s in separator]
# append to new list and return the len of possible combinations, min and max value
lst.append(len(together))
lst.append(min(together))
lst.append(max(together))
#print(lst)
return lst
proc_arr(['1','2','2','3','2','3'])
However, I don't understand why I do don't get the right amount of permutations.
input: proc_arr(['1', '2', '2', '3', '2', '3']) output: [60, 122233, 332221]
and I get [720, 122233, 332221]
another example of input & output
input: proc_arr(['1','2','3','0','5','1','1','3']) output: [3360, 1112335, 53321110]
You appear to be counting the same permutation multiple times because you re treating digits that appear multiple times as distinct. That is, for example, 122233 and 122233 are each counted because one has the "first" 3 first, and the second does not.
One solution would be to compute how many duplicates you will have and eliminate them from your count. In your example, there are 3 2s, so there are 1*2*3=6 ways they can be arranged whilst leaving everything else the same; thus, your answer is 6 times too big due to the 2's. Similarly for the 2 3s: 1*2=2 ways, so divide your answer by 2. This gets you to 720/6/2 = 60, the correct answer.
Python for loop isn't iterating '0' from a list!
I tried to make a code to separate an input into numbers and letters(or operators):
g='10+10+20x'
t=[]
for each_g in g:
t.append(each_g)
lol=[]
a=[]
for each_t in t:
if each_t.isdigit():
lol.append(each_t)
x = t.index(each_t)
t.pop(x)
else:
lol = ''.join(lol)
a.append(lol)
a.append(each_t)
lol=[]
print(a)
The desired output would be:
['10', '+', '10', '+', '20', 'x']
but it prints
['1', '+', '1', '+', '2', 'x']
instead.
Is there any problems whit the code or a better solution to make it work as expected?
Thanks.
Don't modify a sequence that you're iterating over. Each pop is shifting a character down before you can process it.
In this case since you're not using t when you're done, there's no need for the pop at all - it's redundant.
Here's an alternative approach (as your code already has been thoroughly discussed by others):
In [38]: import re
In [39]: g='10+10+20x'
In [40]: re.findall('(\d+|[a-zA-Z]+|\+)',g)
Out[40]: ['10', '+', '10', '+', '20', 'x']
Editing a list (or any other iterable) while you're iterating over it is a horrible idea.
Here's how iterating over a list works:
when you say for each_t in t, what's actually happening is that a sequence of numbers is generated in turn; first 0, then 1 and so forth, all the way up to len(t)-1. The iterator then gets the element at that index and assigns it to each_t.
When you pop from that list, you are eliminating an index. Therefore, what used to be at index 3 is now at index 2 (if you popped something at an index less than 3). Then what happens is that the iterator accesses the element at the next number. But since the elements have essentially shifted down an index, when the iterator asks for the element at index i, it means "give me the element that used to be at index i". Instead, what it gets is "the element currently at index i, which is indeed the element that used to be at index i+1".
This is exactly why you skip over elements when you delete from a list as you're iterating over it
I have no clue about Python and started to use it on some files. I managed to find out how to do all the things that I need, except for 2 things.
1st
>>>line = ['0', '1', '2', '3', '4', '5', '6']
>>>#prints all elements of line as expected
>>>print string.join(line)
0 1 2 3 4 5 6
>>>#prints the first two elements as expected
>>>print string.join(line[0:2])
0 1
>>>#expected to print the first, second, fourth and sixth element;
>>>#Raises an exception instead
>>>print string.join(line[0:2:4:6])
SyntaxError: invalid syntax
I want this to work similar to awk '{ print $1 $2 $5 $7 }'. How can I accomplish this?
2nd
how can I delete the last character of the line? There is an additional ' that I don't need.
Provided the join here is just to have a nice string to print or store as result (with a coma as separator, in the OP example it would have been whatever was in string).
line = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
print ','.join (line[0:2])
A,B
print ','.join (line[i] for i in [0,1,2,4,5,6])
A,B,C,E,F,G
What you are doing in both cases is extracting a sublist from the initial list. The first one use a slice, the second one use a list comprehension. As others said you could also have accessed to elements one by one, the above syntaxes are merely shorthands for:
print ','.join ([line[0], line[1]])
A,B
print ','.join ([line[0], line[1], line[2], line[4], line[5], line[6]])
A,B,C,E,F,G
I believe some short tutorial on list slices could be helpfull:
l[x:y] is a 'slice' of list l. It will get all elements between position x (included) and position y (excluded). Positions starts at 0. If y is out of list or missing, it will include all list until the end. If you use negative numbers you count from the end of the list. You can also use a third parameter like in l[x:y:step] if you want to 'jump over' some items (not take them in the slice) with a regular interval.
Some examples:
l = range(1, 100) # create a list of 99 integers from 1 to 99
l[:] # resulting slice is a copy of the list
l[0:] # another way to get a copy of the list
l[0:99] # as we know the number of items, we could also do that
l[0:0] # a new empty list (remember y is excluded]
l[0:1] # a new list that contains only the first item of the old list
l[0:2] # a new list that contains only the first two items of the old list
l[0:-1] # a new list that contains all the items of the old list, except the last
l[0:len(l)-1] # same as above but less clear
l[0:-2] # a new list that contains all the items of the old list, except the last two
l[0:len(l)-2] # same as above but less clear
l[1:-1] # a new list with first and last item of the original list removed
l[-2:] # a list that contains the last two items of the original list
l[0::2] # odd numbers
l[1::2] # even numbers
l[2::3] # multiples of 3
If rules to get items are more complex, you'll use a list comprehension instead of a slice, but it's another subjet. That's what I use in my second join example.
You don't want to use join for that. If you just want to print some bits of a list, then specify the ones you want directly:
print '%s %s %s %s' % (line[0], line[1], line[4], line[6])
Assuming that the line variable should contain a line of cells, separated by commas...
You can use map for that:
line = "1,2,3,4,5,6"
cells = line.split(",")
indices=[0,1,4,6]
selected_elements = map( lambda i: cells[i], indices )
print ",".join(selected_elements)
The map function will do the on-the-fly function for each of the indices in the list argument. (Reorder to your liking)
You could use the following using list comprehension :
indices = [0,1,4,6]
Ipadd = string.join([line[i] for i in xrange(len(line)) if i in indices])
Note : You could also use :
Ipadd = string.join([line[i] for i in indices])
but you will need a sorted list of indices without repetition of course.
Answer to the second question:
If your string is contained in myLine, just do:
myLline = myLine[:-1]
to remove the last character.
Or you could also use rstrip():
myLine = myLine.rstrip("'")
>>> token = ':'
>>> s = '1:2:3:4:5:6:7:8:9:10'
>>> sp = s.split(token)
>>> token.join(filter(bool, map(lambda i: i in [0,2,4,6] and sp[i] or False, range(len(sp)))))
'1:3:5:7'
l = []
l.extend(line[0:2])
l.append(line[5]) # fourth field
l.append(line[7]) # sixth field
string.join(l)
Alternatively
"{l[0]} {l[1]} {l[4]} {l[5]}".format(l=line)
Please see PEP 3101 and stop using the % operator for string formatting.