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

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);

Related

Multi-values needs to be exported to excel to different rows using lotus script

I was trying to export the Multi-valued field but couldn't able to achieve it. i tried Ubound to export but the scenario is I need the 1st value in 1st row and 2nd value in 2nd row vice versa. Please help me to solve this. I'm using excel application to export the data.
Thanks in advance.
ForAll b In fieldList
If UBound(doc.getitemvalue(b)) <1 Then
worksheet.cells(i,j).value =doc.getitemvalue(CStr(b))
Else
'Join(doc.getitemvalue(CStr(b)),Chr(10))
worksheet.cells(i,j).value =Join(doc.getitemvalue(CStr(b)),Chr(10))
End If
End Forall
Create a loop that goes through all the values for each field by index ("x" in my code sample). Use x again to offset the row value.
You will have a problem that each fieldName's values will be overwritten in the spreadsheet, because i and j are always the same, so if you have more than one fieldName in your fieldList you will need to do something about that too. In my example, I have incremented j for each fieldName so that they will be in different spreadsheet columns
ForAll fieldName In fieldList
For x = LBound(doc.getitemvalue(fieldName)) to Ubound(doc.getitemvalue(fieldName))
worksheet.cells(i + x, j).value = doc.getitemvalue(fieldName)(x)
Next
j = j + 1
End Forall
Alternative version to achieve what you ask in your comment:
ForAll fieldName In fieldList
For x = LBound(doc.getitemvalue(fieldName)) to Ubound(doc.getitemvalue(fieldName))
worksheet.cells(i, j + x).value = doc.getitemvalue(fieldName)(x)
Next
i = i + 1
End Forall
Lets assume the following document:
Fieldname
Value 0
Value 1
Value 2
FirstField
Value0-First
SecondField
Value0-Second
Value1-Second
Value2-Second
ThirdField
Value0-Third
Value1-Third
Solution 1:
If you want the result to look like this
FirstField
SecondField
ThirdField
Value0-First
Value0-Second
Value0-Third
Value1-Second
Value1-Third
Value2-Second
Then you use the following code:
cellY = 2
cellX = 1
Forall fieldName in fieldNameList
For y = 0 to ubound( doc.GetitemValue( fieldName ) )
worksheet.cells(cellY + y, cellX).value = doc.GetitemValue( fieldName )(y)
Next
cellX = cellX + 1
End Forall
Solution 2: If you want the result to look like this
Fieldname
Value 0
Value 1
Value 2
FirstField
Value0-First
SecondField
Value0-Second
Value1-Second
Value2-Second
ThirdField
Value0-Third
Value1-Third
Then you use the following code:
cellY = 1
cellX = 2
Forall fieldName in fieldNameList
For x = 0 to ubound( doc.GetitemValue( fieldName ) )
worksheet.cells(cellY, cellX+x).value = doc.GetitemValue( fieldName )(x)
Next
cellY = cellY + 1
End Forall
Solution 3:
If you want the result to look like this
All fields
FirstField
Value0-First
SecondField
Value0-Second
Value1-Second
Value2-Second
ThirdField
Value0-Third
Value1-Third
Then you use the following code:
cellY = 1
cellX = 1
Forall fieldName in fieldNameList
worksheet.cells(cellY, cellX).value = fieldName
For y = 0 to ubound( doc.GetitemValue( fieldName ) )
cellY = cellY + 1
worksheet.cells(cellY, cellX).value = doc.GetitemValue( fieldName )(y)
Next
cellY = cellY + 1
End Forall
doc.getitemvalue(CStr(b)) always returns a variant array, even when the Ubound is less than one.
The code in your Then clause needs to dereference the 0th entry of the array:
worksheet.cells(i,j).value =doc.getitemvalue(CStr(b))(0)

How to filter symmetric words from a column of data?

I have a list of words and I would like to find all symmetric words and some how put value 1 for each of them (see the picture).
This does the trick:
=1*(A1=CONCAT(MID(A1,LEN(A1)-SEQUENCE(1,LEN(A1),0),1)))
It reads the string in a cell backwards using MID and SEQUENCE, and compares the CONCAT result with the original to see if it is the same, i.e. the string is symmetric.
Multiplying by 1 forces the Boolean into an integer.
With VBA. This assumes that a single character is symmetric:
Public Function Sym(s As String) As Long
Dim L As Long, L2 As Long
Dim p1 As String, p2 As String
L = Len(s)
L2 = Int(L / 2)
Sym = 0
If L Mod 2 = 0 Then
' even
p1 = Mid(s, 1, L2)
p2 = StrReverse(Mid(s, L2 + 1))
If p1 = p2 Then
Sym = 1
End If
Else
' odd
p1 = Mid(s, 1, L2)
p2 = StrReverse(Mid(s, L2 + 2))
If p1 = p2 Then
Sym = 1
End If
End If
End Function
This will handle both an even or odd number of characters.
EDIT#1:
Simply:
Public Function Sym(s As String) As Long
Sym = 0
If s = StrReverse(s) Then Sym = 1
End
With Microsoft365, try:
Formula in B1:
=EXACT(A1,CONCAT(MID(A1,SEQUENCE(LEN(A1),,LEN(A1),-1),1)))
Formula in C1:
=--EXACT(A1,CONCAT(MID(A1,SEQUENCE(LEN(A1),,LEN(A1),-1),1)))
If you are working in a version without CONCAT() it will get significatly more verbose, but still possible:
=SUMPRODUCT(--EXACT(MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1),MID(A1,(LEN(A1)+1)-ROW(A$1:INDEX(A:A,LEN(A1))),1)))=LEN(A1)
This, again, can be wrapped to return either 1 or 0 if you prefer that over the boolean results:
=--(=SUMPRODUCT(--EXACT(MID(A1,ROW(A$1:INDEX(A:A,LEN(A1))),1),MID(A1,(LEN(A1)+1)-ROW(A$1:INDEX(A:A,LEN(A1))),1)))=LEN(A1))

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)

cell array of strings to matrix

A = {'a','b','c','b','a',...}
A is a <1X400> cell array and I want to create a matrix from A such that if the cell is a, the matrix shows 1, if it is b, it shows as 2 in the matrix and 3 for c.
Thank you.
Specific Case
For a simple specific case as listed in the question, you can use char to convert all the cell elements to characters and then subtract 96 from it, which is ascii equivalent of 'a'-1 -
A_numeric = char(A)-96
Sample run -
>> A
A =
'a' 'b' 'c' 'b' 'a'
>> A_numeric = char(A)-96
A_numeric =
1
2
3
2
1
Generic Case
For a generic substitution case, you need to do a bit more of work like so -
%// Inputs
A = {'correct','boss','cat','boss','correct','cat'}
newcellval = {'correct','cat','boss'}
newnumval = [8,2,5]
[unqcell,~,idx] = unique(A,'stable')
[~,newcell_idx,unqcell_idx] = intersect(newcellval,unqcell,'stable')
A_numeric = newnumval(changem(idx,newcell_idx,unqcell_idx))
Sample input-output -
>> A,newcellval,newnumval
A =
'correct' 'boss' 'cat' 'boss' 'correct' 'cat'
newcellval =
'correct' 'cat' 'boss'
newnumval =
8 2 5
>> A_numeric
A_numeric =
8 5 2 5 8 2
That's easy:
result = cell2mat(A)-'a'+1
For a generic association of letters to numbers 1,2,3...:
letters2numbers = 'abc'; %// 'a'->1, 'b'->2 etc.
[~, result] = ismember(cell2mat(A), letters2numbers)
For a generic association of strings to numbers 1,2,3...:
strings2numbers = {'hi', 'hello', 'hey', 'good morning', 'howdy'};
A = {'hello', 'hi', 'hello', 'howdy', 'bye'};
[~, result] = ismember(A, strings2numbers)
In this example,
result =
2 1 2 5 0
use a For Loop which iterate over A and convert character to number
for loop = 1:length(A)
outMat(loop) = char(A(loop)) - 96
end
I hope it works.

Resources