Comparing two lists on Python - python

I need help comparing two lists and returning the indices that they don't match.
a = [0, 1, 1, 0, 0, 0, 1, 0, 1]
b = [0, 1, 1, 0, 1, 0, 1, 0, 0]
indices 4 and 8 don't match and i need to return that as a list [4,8]
I've tried a few methods but they haven't worked for me.

Use zip to iterate over both lists at the same time and enumerate to get the indices during iteration, and write a list comprehension that filters out the indices where the list values don't match:
>>> [i for i, (x, y) in enumerate(zip(a, b)) if x != y]
[4, 8]

You could also just use a simple loop which scans the lists, item by item:
a = [0, 1, 1, 0, 0, 0, 1, 0, 1]
b = [0, 1, 1, 0, 1, 0, 1, 0, 0]
diff=[]
for i in range(0,len(a)):
if a[i]!=b[i]:
diff.append(i)
print diff
A list comprehension could also do the same thing:
diff=[i for i in range(len(a)) if a[i]!=b[i]]
print diff

If you are happy to use a 3rd party library, numpy provides one way:
import numpy as np
a = np.array([0, 1, 1, 0, 0, 0, 1, 0, 1])
b = np.array([0, 1, 1, 0, 1, 0, 1, 0, 0])
res = np.where(a != b)[0]
# array([4, 8], dtype=int64)
Relevant: Why NumPy instead of Python lists?

You can use zip :
a = [0, 1, 1, 0, 0, 0, 1, 0, 1]
b = [0, 1, 1, 0, 1, 0, 1, 0, 0]
count=0
indices=[]
for i in zip(a,b):
if i[0]!=i[1]:
indices.append(count)
count+=1
print(indices)
output:
[4, 8]

Related

How can I combine multiple lists of separated bit values into strings?

I have a list of lists containing 32 individual bits. I want to separate these values into 4 strings of binary digits, each representing a byte.
My data looks like:
array = [[1, 0, 0, 0, 1, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 0, 1, 1]]
The result should satisfy
array[0] == '10001010'
array[1] == '01100000'
array[2] == '00001000'
array[3] == '00111011'
Every solution I've tried leaves me with a string containing commas, such as '1,0,0,0,1,0,1,0'.
What is the simplest way to take each of these byte groupings and convert them into a string?
Use a list comprehension to iterate the items, and join each item by converting it to a string:
>>> array = [[1, 0, 0, 0, 1, 0, 1, 0],
... [0, 1, 1, 0, 0, 0, 0, 0],
... [0, 0, 0, 0, 1, 0, 0, 0],
... [0, 0, 1, 1, 1, 0, 1, 1]]
>>> array = [''.join(str(n) for n in item) for item in array]
>>> array
['10001010', '01100000', '00001000', '00111011']
Try this:
arr1, arr2, arr3, arr4 = [''.join(map(str,elem)) for elem in arr]
print(arr1, arr2, arr3, arr4, sep='\n')
10001010
01100000
00001000
00111011
or without tuple unpacking:
arr = ["".join(map(str, elem)) for elem in arr]
print(arr)
['10001010', '01100000', '00001000', '00111011']
Then you can access them with arr[0] etc..

Setting indicators based in index per row in numpy

I am looking for an efficient way to set a indicators from zero to a known number (which differs for each row).
e.g.
a =
array([[1, 1, 1, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 0]])
and I know the vector with the index when a goes from 1 to zero.
b = [3, 1, 6, 2, 8]
Rather than filling all the rows of a using a for-loop, I want to know if there is a fast way to set these indicators.
Use outer-comparison on ranged array vs. b -
In [16]: ncols = 9
In [17]: b
Out[17]: [3, 1, 6, 2, 8]
In [19]: np.greater.outer(b,np.arange(ncols)).view('i1')
Out[19]:
array([[1, 1, 1, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 0]], dtype=int8)
Other similar ways to express the same -
(np.asarray(b)[:,None] > np.arange(ncols)).view('i1')
(np.asarray(b)[:,None] > np.arange(ncols)).astype(int)
With b being an array, simplifies further, as we can skip the array conversion with np.asarray(b).
Simplest way I can think of is:
result=[]
for row in array:
result.append(row.tolist().index(0))
print(result)
[3, 1, 6, 2, 8]
The reason this works is, that list has a method called index, which tells the first occurrence of a specific item in the list. So I am iterating over this 2-dimentional array, converting each of it to list and using index of 0 on each.
You can store these values into another list and append to it for each row and that's it.
You can use broadcasting to do an outer comparison:
b = np.asarray([3, 1, 6, 2, 8])
a = (np.arange(b.max() + 1) < b[:, None]).astype(int)
# array([[1, 1, 1, 0, 0, 0, 0, 0, 0],
# [1, 0, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 1, 1, 0, 0, 0],
# [1, 1, 0, 0, 0, 0, 0, 0, 0],
# [1, 1, 1, 1, 1, 1, 1, 1, 0]])

How to iterate through a matrix column in python

I have a matrix with the cell values only 0 or 1.
I want to count how many ones or zeros are there in the same row or column to a given cell.
For example, the value matrix[r][c] is 1, so I want to know how many ones are there in the same row. This code does that:
count_in_row = 0
value = matrix[r][c]
for i in matrix[r]:
if i == value:
count_in_row += 1
The for cycle iterates through the same row and counts all ones (cells with the same value).
What if I want to do the same process with columns? Will I iterate through the whole matrix or it is possible through just one column?
PS: I don't want to use numpy, transpose or zip; better with composite cycle.
You have not specified what the datatype of your matrix is. If it is a list of lists, then there is no way to "get just one column", but the code still is similar (assuming that r and c are of type int):
I added the functionality to only count the cells adjacent to the cell in question (above, below, left and right; does NOT consider diagonals); this is done checking that the difference between indexes is not greater than 1.
count_in_row = 0
count_in_col = 0
value = matrix[r][c]
for j in range(len(matrix[r])):
if abs(j - c) <= 1: # only if it is adjacent
if matrix[r][j] == value:
count_in_row += 1
for i in range(len(matrix)):
if abs(i - r) <= 1: # only if it is adjacent
if matrix[i][c] == value:
count_in_col += 1
Or if following the way you started it (whole rows and columns, not only adjacent ones):
for col_val in matrix[r]:
if col_val == value:
count_in_row += 1
for row in matrix:
if row[c] == value:
count_in_col += 1
If you will be doind this for a lot of cells, then there are better ways to do that (even without numpy, but numpy is defenitively a very good option).
You can create a list for rows and cols and simply iterate over your matrix once while adding up the correct parts:
Create demodata:
import random
random.seed(42)
matrix = []
for n in range(10):
matrix.append(random.choices([0,1],k=10))
print(*matrix,sep="\n")
Output:
[1, 0, 0, 0, 1, 1, 1, 0, 0, 0]
[0, 1, 0, 0, 1, 1, 0, 1, 1, 0]
[1, 1, 0, 0, 1, 0, 0, 0, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 1, 1, 1, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
[0, 1, 1, 0, 1, 0, 1, 0, 0, 0]
[1, 0, 1, 1, 0, 0, 1, 1, 0, 0]
[0, 1, 1, 0, 0, 0, 1, 1, 1, 1]
Count things:
rows = [] # empty list for rows - you can simply sum over each row
cols = [0]*len(matrix[0]) # list of 0 that you can increment while iterating your matrix
for row in matrix:
for c,col in enumerate(row): # enumerate gives you the (index,value) tuple
rows.append( sum(x for x in row) ) # simply sum over row
cols[c] += col # adds either 0 or 1 to the col-index
print("rows:",rows)
print("cols:",cols)
Output:
rows: [4, 5, 5, 9, 2, 4, 6, 4, 5, 6] # row 0 == 4, row 1 == 5, ...
cols: [6, 6, 5, 4, 6, 5, 5, 5, 5, 3] # same for cols
Less code but taking 2 full passes over your matrix using zip() to transpose the data:
rows = [sum(r) for r in matrix]
cols = [sum(c) for c in zip(*matrix)]
print("rows:",rows)
print("cols:",cols)
Output: (the same)
rows: [4, 5, 5, 9, 2, 4, 6, 4, 5, 6]
cols: [6, 6, 5, 4, 6, 5, 5, 5, 5, 3]
You would have to time it, but the overhead of two full iteration and the zipping might be still worth it, as the zip() way is inheritently more optimized then looping over a list. Tradeoff might only be worth it for / up to / up from certain matrix sizes ...
I will not solve that for you, but maybe hint in the right direction...
# assuming a list of lists of equal length
# without importing any modules
matrix = [
[1, 0, 0, 0],
[1, 1, 0, 0],
[1, 1, 1, 0],
[1, 1, 1, 1],
]
sum_rows = [sum(row) for row in matrix]
print(sum_rows) # [1, 2, 3, 4]
sum_columns = [sum(row[i] for row in matrix) for i in range(len(matrix[0]))]
print(sum_columns) # [4, 3, 2, 1]
This is a solution with just one for loop:
count_in_row = 0
count_in_column = 0
value = matrix[r][c]
for index, row in enumerate(matrix):
if index == r:
count_in_row = row.count(value)
if row[c] == value:
count_in_column += 1
print(count_in_row, count_in_column)
With numpy it's 1 command (each direction) and much faster
import numpy as np
A = np.array([[1, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 1, 0, 0, 1, 1, 0, 1, 1, 0],
[1, 1, 0, 0, 1, 0, 0, 0, 1, 1],
[1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 1, 1, 0, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
[0, 1, 1, 0, 1, 0, 1, 0, 0, 0],
[1, 0, 1, 1, 0, 0, 1, 1, 0, 0],
[0, 1, 1, 0, 0, 0, 1, 1, 1, 1]])
rowsum = A.sum(axis=1)
colsum = A.sum(axis=0)
print("A ="); print(A);print()
print("rowsum:",rowsum)
print("colsum:",colsum)
rowsum: [4 5 5 9 2 4 6 4 5 6]
colsum: [6 6 5 4 6 5 5 5 5 3]

Take array of indices, find matching indices in another array and replace values

I have two arrays, one array that contains all indices of two arrays that meet a certain condition I had made previous to this. The other array is an array of booleans. I want to take the array of indices and find the same place in the array of booleans and replace those values.
So for example what I am looking to do is:
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
and change myBools to:
myBools = [0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
I've tried:
myBools = [myBools[i] for i in myIdx == 0]
But this does not give me the desired output.
I hope this works (not sure what you need):
myIdxs = [0, 3, 5]
myBools = [1, 1, 1, 1, 1, 0]
myBools = [myBools[i] if i in myIdxs else 0
for i in xrange(len(myBools))]
>>> print myBools
[1, 0, 0, 1, 0, 0]
Poorly worded question, but here are two answers, both are extremely simple and straightforward, and don't required complex list comprehension.
If you want to change the bit to the opposite value
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
for i in myIdxs:
myBools[i] ^= 1 # Bitwise operator flips the bit
print(myBools)
If you want to change the bit to zero.
myIdxs = [0, 3, 5]
myBools = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1]
for i in myIdxs:
myBools[i] = 0 # Sets bit to zero
print(myBools)
Output
The output is actually the same for both, given the input, but don't let that fool you they do two very different things.
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1]
Try using list comprehension with if-else statement.
[myBools[i] if i in myIdxs else 0 for i in range(len(myBools))]
Output
[1, 0, 0, 1, 0, 0]

Selecting indexes of elements with a common property in Python

I have a numpy array and would like to obtain the indexes of the elements that verify a common property. For example, suppose the array is np.array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1]), and I want to have the indexes of all elements equal to 1, so the output would be [0, 4, 5, 8, 10, 14].
I have defined the following procedure
def find_indexes(A):
res = []
for i in range(len(A)):
if A[i] == 1:
res.append(i)
return res
Is there a more "pythonesque" way of doing this? More specifically, I am wondering if there is something similar to boolean indexing:
A[A>=1]
that would return the indexes of the elements rather than the elements themselves.
use np.where.
import numpy as np
x = np.array(np.array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1])
indices, = np.where(x == 1)
print(indices)
Use numpy.where
arr = np.array([1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1])
print np.where(arr == 1)
(array([ 0, 4, 5, 8, 10, 14]),)
List comprehension for pure python:
ar = [i for i in range(len(a)) if a[i] == 1]

Categories

Resources