Python - Find a Number in a String List and return String+Number - python-3.x

Need this:
a_1 = 10
a_2 = 15
a_3 = 4
a_4 = 25
x = 3
a_(x) = 4
I tried this:
list = ["a_1", "a_2", "a_3", "a_4"]
x = 3
matching = [s for s in list if (x) in s]
TypeError: 'in ' requires string as left operand, not int
So:
list = ["a_1", "a_2", "a_3", "a_4"]
x = "3"
matching = [s for s in list if (x) in s]
matching = 'a_3'
It worked, but is there a better way?

I really did not know how to ask, all I needed was this:
eval("a_" + str(x))
thx all

Related

Pythonic way of finding differences between two strings

a = "3030104AF43B000A3F1D200619D09FE00403031324354650004FFFFF"
b = "3030104BE3B000C3DF1D200617183BA00403030335F5B6F0004FFFFF"
Let's say a and b are two hexadecimal string values of which are equal and even in length. They also share the same format such that differences occurring between both strings always happen at the same position (But, initially I do not know which position these differences occur). For example a's first six digits are the same as b's first six digits. i.e., 303010. The following 4 digits are different 4AF43B in a compared with b, after which the next two digit are the same for a and b (00). This pattern follows on until the end of both strings.
I have written code to store the differences occurring as different elements in a list.
seed = "3030104AF43B000A3F1D200619D09FE00403031324354650004FFFFF"
seed2 = "3030104BE3B000C3DF1D200617183BA00403030335F5B6F0004FFFFF"
seed = seed.rstrip("FF")
seed2 = seed2.rstrip("FF")
differences_list1 = []
differences_list2 = []
sequence1 = ""
sequence2 = ""
for pair in range(int(len(seed) / 2)):
data_pair1 = seed[pair * 2:(pair * 2) + 2]
data_pair2 = seed2[pair * 2:(pair * 2) + 2]
if data_pair1 == data_pair2:
if sequence1 == "" and sequence2 == "":
continue
# here, we know it is not an empty sequence
differences_list1.append(sequence1)
differences_list2.append(sequence2)
sequence1 = ""
sequence2 = ""
continue
# when they are not equal to each other
sequence1 = sequence1 + data_pair1
sequence2 = sequence2 + data_pair2
print(str(differences_list1))
print(str(differences_list2))
Output (which I want):
['4AF43B', '0A3F', '19D09FE0', '1324354650']
['4BE3B0', 'C3DF', '17183BA0', '0335F5B6F0']
I've gotten the output as I desired somehow but I would like to know how can I improve/write my code in a more pythonic way (specifically python3.9)?

How to split a string into sub strings of n length?

How would i split a string into sub array's of n length in Matlab?
eg.
Input: "ABCDEFGHIJKL", with sub arrays of length 3
Output: {ABC}, {DEF}, {GHI}, {JKL}
If the string length is not a multiple of n you probably need a loop or arrayfun:
x = 'ABCDEFGHIJK'; % length 11
n = 3;
result = arrayfun(#(k) x(k:min(k+n-1, end)), 1:n:numel(x), 'UniformOutput', false)
Alternatively, accumarray can be used as well:
x = 'ABCDEFGHIJK';
n = 3;
result = accumarray(floor((0:numel(x)-1).'/n)+1, x, [], #(t) {t.'}).';
Either of the above gives, in this example,
result =
1×4 cell array
{'ABC'} {'DEF'} {'GHI'} {'JK'}
A regular expression can do the job here:
str = 'abcdefgh'
exp = '.{1,3}' %the regular expression (get all the group of 3 char, if number of char left < 3, take the rest)
res = regexp(str,exp,'match')
which give:
res =
1×3 cell array
{'abc'} {'def'} {'gh'}
If you only want to match group of 3 char:
exp = '.{3}' %this will output {'abc'} {'def'} but no {'gh'}
This shoud do it :)
string = cellstr(reshape(string, 3, [])')

Append to a list using a for loop

I am using the following code to assign a value to a given letter (A = +1, B= -1)
letList = []
let1 = ['A','A','B']
count = 0
for l in let1:
if l == "A":
count = count + 1
else:
count = count - 1
print(letList.append(count)) #doesnt work
Goal: I want to create a list of counts with the final output that looks something like this: letList = [1,2,1]
Problem: But when I try to append using letList.append(count) I get a none output
Suggestions?
You are trying to print the append function and the append needs to be in your loop to do what you want. Below is an example that prints [1,2,1] using append.
letList = []
let1 = ['A','A','B']
count = 0
for l in let1:
if l == "A":
count = count + 1
else:
count = count - 1
letList.append(count)
print(letList)

Compare 1 string with a cell array of strings with indexes (Matlab)

I have 1 string and 1 cell array of srings :
F = 'ABCD'
R = {'ACBD','CDAB','CABD'};
I would like to compare the string F with all of the strings in R as follows: F(1)='A' and R{1}(1)='A', we will count 1 ( because they have the same value 'A') , F(2)='B' and R{1}(2)='C' we will count 0 ( because they have different values)...and like that until the end of all strings.
We will get same = 2 , dif = 2 for this 'ABCD' and 'ACBD'.
How can I compare F with all the elements in R in the above rule and get the total(same) and total(dif) ?
Assuming all strings in R has the same length as F you can use cellfun:
same = cellfun( #(r) sum(F==r), R )
Results with
2 0 1
That is, the same value per string in R. If you want dif:
dif = numel(F)-same;
If you want the totals:
tot_same = sum(same);
tot_dif = sum(dif);

String lexicographical permutation and inversion

Consider the following function on a string:
int F(string S)
{
int N = S.size();
int T = 0;
for (int i = 0; i < N; i++)
for (int j = i + 1; j < N; j++)
if (S[i] > S[j])
T++;
return T;
}
A string S0 of length N with all pairwise distinct characters has a total of N! unique permutations.
For example "bac" has the following 6 permutations:
bac
abc
cba
bca
acb
cab
Consider these N! strings in lexicographical order:
abc
acb
bac
bca
cab
cba
Now consider the application of F to each of these strings:
F("abc") = 0
F("acb") = 1
F("bac") = 1
F("bca") = 2
F("cab") = 2
F("cba") = 3
Given some string S1 of this set of permutations, we want to find the next string S2 in the set, that has the following relationship to S1:
F(S2) == F(S1) + 1
For example if S1 == "acb" (F = 1) than S2 == "bca" (F = 1 + 1 = 2)
One way to do this would be to start at one past S1 and iterate through the list of permutations looking for F(S) = F(S1)+1. This is unfortunately O(N!).
By what O(N) function on S1 can we calculate S2 directly?
Suppose length of S1 is n, biggest value for F(S1) is n(n-1)/2, if F(S1) = n(n-1)/2, means it's a last function and there isn't any next for it, but if F(S1) < n(n-1)/2, means there is at least one char x which is bigger than char y and x is next to y, find such a x with lowest index, and change x and y places. let see it by example:
S1 == "acb" (F = 1) , 1 < 3 so there is a char x which is bigger than another char y and its index is bigger than y, here smallest index x is c, and by first try you will replace it with a (which is smaller than x so algorithm finishes here)==> S2= "cab", F(S2) = 2.
Now let test it with S2, cab: x=b, y=a, ==> S3 = "cba".\
finding x is not hard, iterate the input, and have a variable name it min, while current visited character is smaller than min, set min as newly visited char, and visit next character, first time you visit a character which is bigger than min stop iteration, this is x:
This is pseudocode in c# (but I wasn't careful about boundaries e.g in input.Substring):
string NextString(string input)
{
var min = input[0];
int i=1;
while (i < input.Length && input[i] < min)
{
min = input[i];
i++;
}
if (i == input.Length) return "There isn't next item";
var x = input[i], y=input[i-1];
return input.Substring(0,i-2) + x + y + input.Substring(i,input.Length - 1 - i);
}
Here's the outline of an algorithm for a solution to your problem.
I'll assume that you have a function to directly return the n-th permutation (given n) and its inverse, ie a function to return n given a permutation. Let these be perm(n) and perm'(n) respectively.
If I've figured it correctly, when you have a 4-letter string to permute the function F goes like this:
F("abcd") = 0
F("abdc") = 1
F(perm(3)) = 1
F(...) = 2
F(...) = 2
F(...) = 3
F(perm(7)) = 1
F(...) = 2
F(...) = 2
F(...) = 3
F(...) = 3
F(...) = 4
F(perm(13)) = 2
F(...) = 3
F(...) = 3
F(...) = 4
F(...) = 4
F(...) = 5
F(perm(19)) = 3
F(...) = 4
F(...) = 4
F(...) = 5
F(...) = 5
F(perm(24)) = 6
In words, when you go from 3 letters to 4 you get 4 copies of the table of values of F, adding (0,1,2,3) to the (1st,2nd,3rd,4th) copy respectively. In the 2nd case, for example, you already have one derangement by putting the 2nd letter in the 1st place; this simply gets added to the other derangements in the same pattern as would be true for the original 3-letter strings.
From this outline it shouldn't be too difficult (but I haven't got time right now) to write the function F. Strictly speaking the inverse of F isn't a function as it would be multi-valued, but given n, and F(n) there are only a few cases for finding m st F(m)==F(n)+1. These cases are:
n == N! where N is the number of letters in the string, there is no next permutation;
F(n+1) < F(n), the sought-for solution is perm(n+(N-1)!), ;
F(n+1) == F(n), the solution is perm(n+2);
F(n+1) > F(n), the solution is perm(n+1).
I suspect that some of this might only work for 4 letter strings, that some of these terms will have to be adjusted for K-letter permutations.
This is not O(n), but it is at least O(n²) (where n is the number of elements in the permutation, in your example 3).
First, notice that whenever you place a character in your string, you already know how much of an increase in F that's going to mean -- it's however many characters smaller than that one that haven't been added to the string yet.
This gives us another algorithm to calculate F(n):
used = set()
def get_inversions(S1):
inv = 0
for index, ch in enumerate(S1):
character = ord(ch)-ord('a')
cnt = sum(1 for x in range(character) if x not in used)
inv += cnt
used.add(character)
return inv
This is not much better than the original version, but it is useful when inverting F. You want to know the first string that is lexicographically smaller -- therefore, it makes sense to copy your original string and only change it whenever mandatory. When such changes are required, we should also change the string by the least amount possible.
To do so, let's use the information that the biggest value of F for a string with n letters is n(n-1)/2. Whenever the number of required inversions would be bigger than this amount if we didn't change the original string, this means we must swap a letter at that point. Code in Python:
used = set()
def get_inversions(S1):
inv = 0
for index, ch in enumerate(S1):
character = ord(ch)-ord('a')
cnt = sum(1 for x in range(character) if x not in used)
inv += cnt
used.add(character)
return inv
def f_recursive(n, S1, inv, ign):
if n == 0: return ""
delta = inv - (n-1)*(n-2)/2
if ign:
cnt = 0
ch = 0
else:
ch = ord(S1[len(S1)-n])-ord('a')
cnt = sum(1 for x in range(ch) if x not in used)
for letter in range(ch, len(S1)):
if letter not in used:
if cnt < delta:
cnt += 1
continue
used.add(letter)
if letter != ch: ign = True
return chr(letter+ord('a'))+f_recursive(n-1, S1, inv-cnt, ign)
def F_inv(S1):
used.clear()
inv = get_inversions(S1)
used.clear()
return f_recursive(len(S1), S1, inv+1, False)
print F_inv("acb")
It can also be made to run in O(n log n) by replacing the innermost loop with a data structure such as a binary indexed tree.
Did you try to swap two neighbor characters in the string? It seems that it can help to solve the problem. If you swap S[i] and S[j], where i < j and S[i] < S[j], then F(S) increases by one, because all other pairs of indices are not affected by this permutation.
If I'm not mistaken, F calculates the number of inversions of the permutation.

Resources