I am having a two dimensional list like:
[[1, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 1, 1, 0], [1, 1, 1, 1]]
and I want to XOR the inner sub-lists with each other. So at some point of time with some combination I will be getting a sub list with all zeros like [0,0,0,0] and if I don't get with two sub lists I have to go for XORing of three sub-lists till I get again [0,0,0,0], if not then, have to go for four sub-lists.
The problem is I can do like picking up two lists and XOR each element then save it in separate sub-list and this works but each time I have to change my code so is there any way to XOR sub-list like [1, 1, 0, 0] ^ [1, 0, 1, 0] instead of doing like lis[i][j]^lis[i+1][j] so that I can manage my code recursively?
You could find shorter but I think this would work:
STOP=[0,0,0,0]
def nxor(l,res=None,p=1):
if not res: res= l[0]
if res == STOP:
return p-1 # or l[:p]
try:
return nxor(l,list(iter.imap (operator.xor, *list([res,l[p]]) )),p+1)
except:
return None # or res
print nxor (l)
It returns the position of the last sub-list that lead to [0,0,0,0]; it would be easy to return the sub-list instead, or the actual result (see comments).
If you want to test all the combinations, you could use itertools:
for i in xrange(2,len(l)):
for j in itertools.combinations(l,i):
print nxor(list(j))
What you could do is to convert the 2-D bit lists to a 1-D number list and then XOR them together.
a = [[1, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 1, 1, 0], [1, 1, 1, 1]]
b = map(lambda x: int("".join(map(lambda y: str(y), x)),2), a)
b is now: [12, 10, 6, 14, 14, 6, 15]
Now you are working with a 1-D list which will make that easier.
Related
oldrow = [1]
for i in range(5):
finaloutputlist.append(oldrow)
print(oldrow)
oldrow.append(0)
oldrow.insert(0,0)
j = i + 1
newrow = []
for i in range(len(oldrow) -1):
#print(oldrow[i])
newrow.append(oldrow[i] + oldrow [i+1])
oldrow = newrow
print(finaloutputlist)
When I run the above code, I get an output of
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[[0, 1, 0], [0, 1, 1, 0], [0, 1, 2, 1, 0], [0, 1, 3, 3, 1, 0], [0, 1, 4, 6, 4, 1, 0]]
There when I print "oldrow", I get exactly the array that I want to append onto my list of arrays in called finaloutputlist .But appending that same oldrow keeps netting me the final output line. For some reason the 0s that I add after updating my finaloutputlist seem to be making their way onto the list.
Thank you to #jasonharper,
finaloutputlist.append(oldrow.copy())
worked amazing, no extra imports needed
what would be the quickest way to get to :
[[0, 2, 0, 0],\
[0, 2, 0, 0],\
[0, 2, 0, 0],\
[0, 2, 0, 0]]
from:
[[0, 0, 2, 0],\
[0, 0, 2, 0],\
[0, 0, 2, 0],\
[0, 0, 2, 0]]
without using numpy or any other external library
For your specific task:
l = [[0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0]]
for arr in l:
arr[1], arr[2] = arr[2], arr[1]
Let's say we have a list l, which is [0, 0, 2, 0], and we want to shift all the elements one place to left.
Firstly, we need to get all the elements to the right except the first one. List slicing l[1:] would work here, which would get [0, 2, 0].
Secondly, we need to get the remaining elements on the left with l[1:], which would get [0].
You can now probably see that we can shift the elements one place to the left with adding the above 2 lists together:
>>> lst = [0, 0, 2, 0]
>>> first = lst[1:]
>>> second = lst[:1]
>>> first + second
[0, 2, 0, 0]
Which can be summarized in this function:
def shift(lst, n):
return lst[n:] + lst[:n]
Since this can shift one lists position, it can applied to all lists in a nested list and shift their positions to left by 1:
nested_lst = [shift(sublist, 1) for sublist in nested_lst]
I have an array of zeros and ones like [0,0,0,1,1,1,0,0,0,1,1]. How to write a program to save neighboring 0's and 1's in different arrays.
E.g.
[0,0,0,1,1,1,0,0,0,1,1] giving [0,0,0],[1,1,1],[0,0,0],[1,1].
You can group them with itertools.groupby, like this
>>> data = [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1]
>>> from itertools import groupby
>>> [list(group) for item, group in groupby(data)]
[[0, 0, 0], [1, 1, 1], [0, 0, 0], [1, 1]]
The result of groupby, will be a tuple of actual item and an iterator which gives the grouped items. We just convert the grouped items to a list, with list(group).
As per the comments,
>>> data = [1, 2, 1, 3, 4, 5, 6, 7, 1, 2, 3]
>>> flag = [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1]
Create a generator which will give the values multiplied,
>>> gen = (d * v for d, v in zip(data, flag))
Now, group based on the result of calling bool on each of the numbers. So, if the bool is called on 0, it will give False, otherwise True.
>>> [list(g) for _, g in groupby(gen, key=bool)]
[[0, 0, 0], [3, 4, 5], [0, 0, 0], [2, 3]]
I am a newbie to python and have been having an issue with list comprehension. Is there a way to extend subsists in a list of list like this
lst = [[0,0,0,0],[[x,x,x,x],[y,y,y,y]],[0,0,0,0],[0,0,0,0]]
I would like to end up with a following list, but I am not sure how to approach the problem:
lst = [[0,0,0,0],[x,x,x,x,y,y,y,y],[0,0,0,0],[0,0,0,0]]
I found this snippet of code but I am not sure how to make it operate on a second "level" of lists. I tried this:
print([x for y in lst for x in y])
Just go through each element and if it has a length of 2 (which means its a donut), add the two elements of that sublist together.
def flatten(data):
new_data = [lists[0]+lists[1] if len(lists) == 2 else lists for lists in data]
return new_data
data = [[1, 2, 3, 4], [[5, 6, 7, 8], [9, 10, 11, 12]], [13, 14, 15, 16]]
new_data = flatten(data)
For the example given, you can do as follows:
x,y=1,2
lst = [[0,0,0,0],[[x,x,x,x],[y,y,y,y]],[0,0,0,0],[0,0,0,0]]
map(lambda l: sum(l,[]) if isinstance(l[0],list) else l, lst)
#gives: [[0, 0, 0, 0], [1, 1, 1, 1, 2, 2, 2, 2], [0, 0, 0, 0], [0, 0, 0, 0]]
I assumed that x=1, and y=2.
Based on the image, it seems you have nested lists in the following way:
x,y=1,2
lst = [[[0,0,0,0]],[[[x,x,x,x],[y,y,y,y]]],[[0,0,0,0]],[[0,0,0,0]]]
# 0, x, and y in you case are lists/touples, but for this example there are ints.
# it should not matter anyway for this example.
map(lambda l: [sum(l[0],[])] if len(l[0])==2 else l, lst)
# relults in: [[[0, 0, 0, 0]], [[1, 1, 1, 1, 2, 2, 2, 2]], [[0, 0, 0, 0]], [[0, 0, 0, 0]]]
I am using numpy to tally a lot of values across many large arrays, and keep track of which positions the maximum values appear in.
In particular, imagine I have a 'counts' array:
data = numpy.array([[ 5, 10, 3],
[ 6, 9, 12],
[13, 3, 9],
[ 9, 3, 1],
...
])
counts = numpy.zeros(data.shape, dtype=numpy.int)
data is going to change a lot, but I want 'counts' to reflect the number of times the max has appeared in each position:
max_value_indices = numpy.argmax(data, axis=1)
# this is now [1, 2, 0, 0, ...] representing the positions of 10, 12, 13 and 9, respectively.
From what I understand of broadcasting in numpy, I should be able to say:
counts[max_value_indices] += 1
What I expect is the array to be updated:
[[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[1, 0, 0],
...
]
But instead this increments ALL the values in counts giving me:
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
...
]
I also though perhaps if I transformed max_value_indices to a 100x1 array, it might work:
counts[max_value_indices[:,numpy.newaxis]] += 1
but this has effect of updating just the elements in positions 0, 1, and 2:
[[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[0, 0, 0],
...
]
I'm also happy to turn the indices array into an array of 0's and 1's, and then add it to the counts array each time, but I'm not sure how to construct that.
You could use so-called advanced integer indexing (aka Multidimensional list-of-locations indexing):
In [24]: counts[np.arange(data.shape[0]),
np.argmax(data, axis=1)] += 1
In [25]: counts
Out[25]:
array([[0, 1, 0],
[0, 0, 1],
[1, 0, 0],
[1, 0, 0]])
The first array, np.arange(data.shape[0]) specifies the row. The second array, np.argmax(data, axis=1) specifies the column.