python lists: merge and replace - python

I am looking for a more elegant/Pythonic way of doing the following task:
I have two string lists A and B, where B is almost a subset of A except that B has a postfix * for some of the elements. My goal is to replace elements in A with those corresponding elements in B that have the postfix. An example:
A = ['abcd', 'ddse', '123d', 'aaaaa']
B = ['ddse', 'aaaaa*']
I'd like to get a list as ['abcd', 'ddse', '123d', 'aaaaa*']. The way I can think of is to split and transform A in to a two-column dataframe and merge with B, then put the * column back to column in B. But that does not look very elegant since I need to do a lot of this operation. Is there a better way of doing it?
Thanks!

If the * is always at the end, it's pretty simple with this code:
C = [(x + '*') if ((x + '*') in B) else x for x in A]
To do the same thing for a list of lists, try this; you will get the results in a list of lists C then:
C = []
for A, B in zip(A_L, B_L):
C.append([x + '*' if ((x + '*') in B) else x for x in A])

What about this?:
def doit(A,B):
for n,i in enumerate(A):
if i + '*' in B:
A[n] = i + '*'

This?
[ e+'*' if e+'*' in B else e for e in A]

So you really want to check, for every element a of A, whether there is some element a* of B, and if there is some a*, to replace a in A with a*.
#make a copy of A with * appended to every element
C = [a + "*" for a in A]
#loop through C and check
for i in range(len(A)):
if C[i] in B:
A[i] = C[i]

Related

Creating an array that multiplies and adds its elements in all unique possible combinations

I am currently working on a project for calculating polynomial shifts via python of nth degree.
The user can input n amount of inputs which get stored in an array that then get converted via the shift and turned back into a new polynomial. The problem is, the higher the degree of n, the more calculations necessary to turn the shifted value to it's polynomial coefficient:
What the program should do is add and multiply all the values uniquely and save the result in a new array:
e.g. for a polynomial of degree 4, it will have inputs [a,b,c,d]
shiftedPCL[0] = a + b + c + d
shiftedPCL[1] = a*b + b*c + c*d + a*c + b*d + a*d
shiftedPCL[2] = a*b*c + b*c*d + a*b*d + a*c*d
shiftedPCL[3] = a*b*c*d
The first and last lines of the equations can be solved simply by summing and multiplying all the values in a list respectively, and I have created a simple recursive code to calculate the second to last line of equations using recursion, but for n greater than 3 it is useless, as it cannot calculate any lines that aren't the first, last or second to last.
This is why I would like to know if there's a way to add and multiply all elements in a list as shown above (for lists of any length).
What you are trying to do is the expansion of a product of monic binomials like
(x+a)(x+b)(x+c)(x+d) = x^4 + Ax^3 + Bx^2 + Cx + D.
Don't do that by means of the (modified) Vieta's formulas. Instead, apply one binomial at a time.
E.g. after three factors already expanded,
(x^3 + Px^2 + Qx + R)(x + d) = x^4 + (P + d) x^3 + (Q + Pd) x^2 + (R + Qd) x + Rd.
The element at index i in your resulting array is the sum of all products of combinations of i elements.
In python, the sum of all products of combinations of i elements from a list l can be written as:
sum(map(prod, combinations(l,i)))
Where sum and map are builtin functions, and prod and combinations are imported from standard library modules math and itertools, respectively.
from itertools import combinations
from math import prod
def sums_of_products(l):
return [sum(map(prod, combinations(l,i))) for i in range(1, len(l)+1)]
We can test this function with numbers, or with symbols using sympy:
from sympy import symbols
a,b,c,d = symbols('a b c d')
print( sums_of_products([a,b,c,d]) )
# [a + b + c + d,
# a*b + a*c + a*d + b*c + b*d + c*d,
# a*b*c + a*b*d + a*c*d + b*c*d,
# a*b*c*d]
print( sums_of_products([2,3,5,7]) )
# [17, 101, 247, 210]
The easiest way to do this in my opinion would be using python itertool. Python itertool is a module that provides various functions that work on iterators to produce complex iterators. The function is itertools permutations. This might be the easiest though slowest program:
from itertools import permutations
list1 = [1,2,3,4] #replace with a, b, c and d
shiftedPCL = []
for i in range(1,len(list1)+1):
comb = permutations(list1, i)
sum1 = 0
for j in comb:
print(j)
result = 1
for x in j:
result = result * x
sum1 += result
shiftedPCL.append(sum1)
print(shiftedPCL)
Variable Names changed as recommended by #Stef

Elegant and/or fast equivalents of Excel SUMXMY2 (sum of square of differences of corresponding array elements) in python

Test Sample:
a = [0.1357678 0.27303184 -0.75600229]
b = [0.3813097 -0.72613616 0.18361217]
I would like to implement SUMXMY2(a, b) in Python without for loops
How can I do this?
As far as I know, - is not a valid operator for lists, so I would use a list comprehension. It does technically use a for loop, however I'd call it "elegant enough".
c = [(b[i] - a[i]) ** 2 for i in range(len(b))]
result = sum(c)
To make it more compact but less readable:
c = sum([(b[i] - a[i]) ** 2 for i in range(len(b))])
If you're dealing with lists of different lengths, use this:
c = [(b[i] - a[i]) ** 2 for i in range(min(len(b), len(a)))]
result = sum(c)
Squared difference is given by:
c = ((a - b) ** 2)
The sum is then simply given by
c = c.sum()
if a and b are lists you can convert them to pandas series first:
a = pd.Series(a)
or to numpy array as:
a = np.asarray(a)

Is there a Python function that does what mapply do in R

Is there a function in Python that can do what Mapply do in R?
Basically I have a list of n inputs(each entry is a dataframe) for a function and corresponding lists(each list has the length of n) of parameters.
In each parameter lists, the position of each parameter corresponds to the respective position of input in the input list.
Now I wish to obtain the result in the exact order of the way I put my input, either in the form of a list with each element a dataframe(or matrix or whatever) or just one dataframe with all result appended. This is easily achievable in R using Mapply, but in python, I haven't got the luck to find any function that does the trick.
I haven't try this but one of the solution that i thought of is to pd.concat all lists(including input list and parameter lists) I got into one bulky list by column and apply the function to each row where I'll extract each element of the row to fill the function.
This might work but it would look quite stupid if there is actually one-line solution.
This is how I would deal with the problem in R:
result <- mapply(FUN = function(input, parameter1, parameter2) function_of_interest(input, parameter1, parameter2), input = input_list, parameter1 = parameter1_list, parameter2 = parameter2_list,... )
If I understand the question correctly, this example of mapply in R:
A <- c(1, 2, 3)
B <- c(2, 3, 4)
my_multiplication <- function(x,y){return(x*y)}
C <- mapply(my_multiplication, A, B)
could be roughly equivalent to this Python code:
a = [1, 2, 3]
b = [2, 3, 4]
def my_multiplication(x, y):
return x * y
c = map(my_multiplication, a, b)
The c is now a so called iterator. If I oversimplify, c can be viewed as a function that returns:
a[0] * b[0] on first call,
a[1] * b[1] on second call,
a[2] * b[2] on third (and last) call
i = 0
message = 'a[{}] * b[{}] = {} * {} = {}'
for result in c:
print(message.format(i, i ,a[i], b[i], result))
i += 1
prints
a[0] * b[0] = 1 * 2 = 2
a[1] * b[1] = 2 * 3 = 6
a[2] * b[2] = 3 * 4 = 12
My answer seems to be a modification of the answer given by #Paolo42, which just wraps the "map" function with a call to "list" to get rid of the loop:
>>> list(map(my_multiplication, A, B) )
[2, 6, 12]
I also liked the list comprehension solution given by #Alexander, but I also appreciate the comment from #Paolo42.

Solve 4*ABCD = DCBA in python

I'm still a beginner and I am trying to do the following exercise:
A, B, C, and D are all different digits. The number DCBA is equal to 4 times the number ABCD. What are the digits? Note: to make ABCD and DCBA conventional numbers, neither A nor D can be zero. Use a quadruple-nested loop.
Here's where I got stuck:
for A in range(0,9):
for B in range(0,9):
for C in range(0,9):
for D in range(0,9):
How to solve 4*ABCD = DCBA using a quadruple-nested loop?
You're almost there - the only thing you're missing is to convert the digits to a whole number, e.g., by multiplying them by their respective "place". BTW, if A and D can't be 0, you should exclude that from the range of values:
for a in range(1,9):
for b in range(0,9):
for c in range(0,9):
for d in range(1,9):
if 4* (1000 * a + 100 * b + 10 * c + d) == \
(a + 10 * b + 100 * c + 1000 * d):
print "a=%d b=%d c=%d d=%d" % (a, b, c, d)
The result, by the way, is:
a=2 b=1 c=7 d=8
The following prints all solutions, don't need a quadruple-nested loop:
for i in range(1000,10000):
if i==4*int(str(i)[::-1]):
print(i)
this is a constraint programming problem that can be solved like this:
need to pip install python-constraint
from constraint import *
problem = Problem()
l = range(10)
for v in ["a", "b", "c", "d"]:
problem.addVariable(v, l)
problem.addConstraint(AllDifferentConstraint())
problem.addConstraint(lambda a, b, c, d : 4*(a*1000+ b*100+ c*10 + d) == 1000*d + 100*c + 10*b + a,
("a", "b", "c", "d"))
print problem.getSolutions()
here the computation time is negligible but for more complex problems, the computation time might be way shorter than embedded loops because the search space is efficiently searched
Here is my answer.
for a in range(1,10):
for b in range(0,10):
for c in range(0,10):
for d in range(1,10):
q=str(a)
w=str(b)
e=str(c)
r=str(d)
t=(q+w+e+r)
u=int(t)
y=t[::-1]
i=int(y)
if u==4*i:
print(i)
print(u)
print(u ,"=4*" ,i)

Comparing Strings

Does there exist any inbuilt function in python than can return number of mathching characters in two strings,for example:
INPUT:
TICK TOCK
CAT DOG
APPLE APPLES
OUTPUT:
3
0
5
The words "TICK" and "TOCK" have a score of 3, since three characters (T, C, K) are the same. Similarly, "CAT" and "DOG" score 0, since no letters match.
I am a new bie in python so please help me with examples.
Here's a version using list comprehensions:
[x == y for (x, y) in zip("TICK", "TOCK")].count(True)
Or, shorter (using operator):
import operator
map(operator.eq, "TICK", "TOCK").count(True)
According to #Kabie, <expr>.count(True) can be replaced by sum(<expr>) in both versions.
There is no built-in function. But you can do it using some simple expressions,.
>>> A, B = sorted("APPLE APPLES".split(), key=len)
>>> len([e for e in A if e in B])
5
If the position and order of the characters are important, then the chosen answer would suffice. The problem is, the given solution will not work if that is not the case.
If position is not important, but the order is, you could write a function that returns the length of the longest common subsequence. Here is a sample implementation:
def lcs(string1, string2):
m = len(string1)
n = len(string2)
C = [[0] * (n + 1)] * (m + 1)
for i in range(m + 1)[1:]:
for j in range(n + 1)[1:]:
if string1[i - 1] == string2[j - 1]:
C[i][j] = C[i - 1][j - 1] + 1
else:
C[i][j] = max(C[i][j - 1], C[i - 1][j])
return C[m][n]
If position and order does not matter, you can use collections.Counter (Python 2.7/3.1; or http://code.activestate.com/recipes/576611/) like so:
def f(string1, string2):
set_string1 = Counter(string1)
set_string2 = Counter(string2)
# get common characters
common = set_string1 & set_string2
# return the sum of the number of occurrences for each character
return reduce(lambda a, b: a + b, common.values())
Yes you import operator by writing
import operator
and use operator.eq method like this:
import operator
operator.eq(String, String)
Hope this will help:
def CommonLetters(s1, s2):
l1=list(''.join(s1.split()))
l2=list(''.join(s2.split()))
return [x for x in l1 if x in l2]
x= CommonLetters('cerberus', 'atorb')
print len(x)

Categories