Create Python List using a True/False expression check? [duplicate] - python

This question already has answers here:
Inconsistent comprehension syntax?
(3 answers)
Closed 7 years ago.
Looking to generate a Python list that uses an if statement to check whether a number is even or odd. If even take the List value as '1' and if odd take the list value as '0'.
Progress to date:
List1 = [x for x in range(0,99) if x % 2 == 0]
However, this only generates a list of even numbers. When I change the expression to add an else check I get a syntax error. Any help appreciated.
List1 = [1 for x in range(0,99) if x % 2 == 0 else 0]

You are using a filter, where you want to alter the left-hand-side expression instead, using a conditional expression:
[1 if x % 2 == 0 else 0 for x in range(99)]
This can be simplified to:
[1 - (x % 2) for x in range(99)]

Change the if else condition present inside the list_comprehension like below.
>>> [1 if x % 2 == 0 else 0 for x in range(0,99)]
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
This would print 1 for even numbers and 0 for odd numbers.

Related

How to smooth list of numerical values in Python?

I have a collection of lists of integer values in python like the following:
[0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
Now I would like to have a somewhat "smoothed" sequence where each value with the same preceding and following value (which both differ from the central value in question) is replaced with this preceeding-following value. So my list above becomes:
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1]
(The order or procession is from left to right, just to reconcile possible conflicting groupings.)
How could I achieve list?
Bonus: same as above with possible parametrization how many preceeding-following values must occur to change the central value (2-2 or 3-3 instead of just 1-1).
A straightforward loop should do the trick:
_list = [0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
for i in range(1, len(_list)-1):
if _list[i-1] == _list[i+1]:
_list[i] = _list[i-1]
print(_list)
Output:
[0, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1]
arr = [0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]
res = [arr[0]]
i = 0
for i in range(1,len(arr)):
if res[i-1] not in arr[i:i+2]:
res.append(arr[i])
else:
res.append(res[i-1] )
print(res)
To allow the number of preceding / following values to be changed, you can create a 'pad' the list and iterate through a moving window on the padded list to check if all surrounding values are the same.
def smooth(lst, values=1, padding=None):
padded = [padding] * values + lst + [padding] * values
for i, n in enumerate(lst):
surrounding = set(padded[i:i+values] + padded[i+values+1:i+values*2+1])
if len(surrounding) == 1:
yield surrounding.pop()
else:
yield n
print(list(smooth([0, 0, 1, 0, 1, 0, 0, 2, 1, 1, 1, 2, 1]))) # [0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1]
If your input list may contain None, choose a different padding parameter when calling the generator.

Is there a function I can use in Python to randomly select elements equal to specified number and change it to another?

For instance, if I have the following distribution, I want to randomly select 4 elements = 1 and change that element to = 0.
lst = [1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0]
-> Function <-
lst = [0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0]
or
lst = [1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
or
lst = [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]
or ....
Using numpy:
ones = np.where(lst)[0]
to_zero = np.random.choice(ones, 4, replace=False)
for i in to_zero: # Alternatively, if lst is an array: lst[to_zero] = 0
lst[i] = 0
To achieve what you want, you first need to get the list of the indexes of the one elements. Then you need to pick 4 random indexes and update the values from the starting list.
Note that you cannot use the random.choices method because it doesn’t return unique values, use random.sample instead.
def update_randomly(tab):
n = range(len(tab))
one_indexes = [i for i in n if tab[i] == 1]
rdm_indexes = random.sample(one_indexes, 4)
return [0 if i in rdm_indexes else tab[i] for i in n]

Program corresponding to Complete Boolean Lattice *Q_n*

I am first year student of Math faculty, and I didn't have programming class yet.
I am working on a project and to simplify my calculations it would be nice to implement a program that would calculate a matrix corresponding to the complete boolean lattice Q_n, which is a set of n integers from 1 to n and all of its possible subsets.
For example, when n=4 the matrix would be the following:
1;0;0;0;1;1;1;0;0;0;1;1;1;0;1
0;1;0;0;1;0;0;1;1;0;1;1;0;1;1
0;0;1;0;0;1;0;1;0;1;1;0;1;1;1
0;0;0;1;0;0;1;0;1;1;0;1;1;1;1
where first column correspond to the subset {1} of {1,2,3,4}, second column to subset {2} of {1,2,3,4}, column 5 for example to subset {1,2} of {1,2,3,4} and so on.
My idea was to create first all zero matrix of the corresponding size and then I do not know how to proceed. Please help me to get ideas.
The itertools module makes this easy. Here is one way:
import itertools
def subset_matrix(n):
A = [[0]*pow(2,n) for _ in range(n)]
j = 0
for k in range(n+1):
for c in itertools.combinations(range(n),k):
for i in c:
A[i][j] = 1
j += 1
return A
#for example:
A = subset_matrix(4)
for row in A:
print(row)
Output:
[0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1]
[0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1]
[0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1]
[0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1]

How to make a NOR between 2 vectors in python

I have two vectors :
predictions = [0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1]
labels = [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0]
and I need as an output (using python) the true negatives - NOR of these two vectors.
output = [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]
I tried with this command but it throw an error :
print not(predictions & labels)
>>>TypeError: unsupported operand type(s) for &: 'list' and 'list'
What is the correct syntax / command to do such a simple thing ?
Native python does not support vector operation. You have to nand individual element
>>> [int(not (p & l)) for p, l in zip(predictions, labels)]
[1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1]
Off -course if you are using numpy, you can achieve what you are envisaging
>>> np.logical_not(np.logical_and(predictions, labels)).astype(int)
array([1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1])
It is worth noting that your output is not Nand but actually Nor, so you have to apply the operations accordingly
>>> np.logical_not(np.logical_or(predictions, labels)).astype(int)
array([1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0])
Here You have to iterate to every item in the list
c=[int(not i&j) for i,j in zip(predictions,labels)]
The operator & is not defined for operands of type list.
The operator not will return True if len(list>0), if the list is empty it will return false.
Also you need to cast booleans to ints to achieve the required result.
With itertools.imap and the operator module:
from operator import eq,and_,or_,xor
from itertools import imap
predictions = [0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1]
labels = [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0]
#Logical AND
print [int(e) for e in imap(and_,predictions,labels)]
#Logical NAND
print [int(not e) for e in imap(and_,predictions,labels)]
#Logical OR
print [int(e) for e in imap(or_,predictions,labels)]
#Logical NOR
print [int(not e) for e in imap(or_,predictions,labels)]
#Logical XOR
print [int(e) for e in imap(xor,predictions,labels)]
#Logical not XOR
print [int(not e) for e in imap(xor,predictions,labels)]

Creating sublist from a give list of items

I would say first that the following question is not for homework purpose even because i've finish software engineer a few months ago. Anyway today I was working and one friend ask to me this strange sorting problem.
"I have a List with 1000 rows, each row represent a number, and I want to create 10 sub lists each have a similar summation of the numbers from the main list. How can I do that?"
For example I've the main list composed by 5,4,3,2 and 1. It's simple, I create two sub lists
one with 5 and 3 the other with 4,2 and 1 the result of each list it's similar: 8 for the first 7 for the second.
I can't figure it out the algorithm even if know it's simple but I'm missing something.
Let A be the input array. I'll assume it is sorted ascending.
A = [2,3,6,8,11]
Let M[i] be the number of sublist found so far to have sum equal to i.
Starts with only M[0] = 1 because there is one list with has sum equals zero, that is the empty list.
M = [1,0,0,...]
Then take each item from the list A one-by-one.
Update the number of ways you have to compose a list of each sum when considering
that the item you just take can be used.
Suppose a is the new item
for each j:
if M[j] != 0:
M_next[j+a] = M[j+a] + M[j]
When you found any M[j] which reach 10 during that, you should stop the algorithm.
Also, modify to remember the items in the list to be able to get the actual list at the end!
Notes:
You can use sparse representation for M
This is similar to those Knapsack and subset sum problems.
Perhaps you might find many better algorithms reading on those.
Here is a working code in Python:
A = [2,3,6,8,11]
t = sum(A)
M = [0]*(t+1)
M[0] = 1
print 'init M :',M
for a in A:
for j in range(len(M)-1,-1,-1):
if M[j] != 0:
M[j+a] += M[j]
print 'use',a,':',M
And its output:
init M : [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
use 2 : [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
use 3 : [1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
use 6 : [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
use 8 : [1, 0, 1, 1, 0, 1, 1, 0, 2, 1, 1, 2, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
use 11 : [1, 0, 1, 1, 0, 1, 1, 0, 2, 1, 1, 3, 0, 2, 2, 0, 2, 2, 0, 3, 1, 1, 2, 0, 1, 1, 0, 1, 1, 0, 1]
Take the interpretation of M[11] = 3 at the end for example;
it means there are 3 sublists with sum equals 11.
If you trace the progress, you can see the sublists are {2,3,6},{3,8},{11}.
To account for the fact that you allow the 10 sublists to have similar sum. Not just exactly the same sum. You might want to change termination condition from "terminate if any M[j] >= 10" to "terminate if sum(M[j:j+3]) >= 10" or something like that.

Categories