removing duplicates - ** only when the duplicates occur in sequence - matlab

I would like to do something similar to the following, except I would only like to remove 'g' and'g' because they are the duplicates that occur one after each other. I would also like to keep the sequence the same.
Any help would be appreciated!!!
I have this cell array in MATLAB:
y = { 'd' 'f' 'a' 'g' 'g' 'w' 'a' 'h'}
ans =
'd' 'f' 'a' 'w' 'a' 'h'

There was an error in my first answer (below) when used on multiple duplicates (thanks grantnz). Here's an updated version:
>> y = { 'd' 'f' 'a' 'g' 'g' 'w' 'a' 'h' 'h' 'i' 'i' 'j'};
>> i = find(diff(char(y)) == 0);
>> y([i; i+1]) = []
y =
'd' 'f' 'a' 'w' 'a' 'j'
OLD ANSWER
If your "cell vector" always contains only single character elements you can do the following:
>> y = { 'd' 'f' 'a' 'g' 'g' 'w' 'a' 'h'}
y =
'd' 'f' 'a' 'g' 'g' 'w' 'a' 'h'
>> y(find(diff(char(y)) == 0) + [0 1]) = []
y =
'd' 'f' 'a' 'w' 'a' 'h'

Look at it like this: you want to keep an element if and only if either (1) it's the first element or (2) its predecessor is different from it and either (3) it's the last element or (4) its successor is different from it. So:
y([true ~strcmp(y(1:(end-1)),y(2:end))] & [~strcmp(y(1:(end-1)),y(2:end)) true])
or, perhaps better,
different = ~strcmp(y(1:(end-1)),y(2:end));
result = y([true different] & [different true]);

This should work:
y([ diff([y{:}]) ~= 0 true])
or slightly more compactly
y(diff([y{:}]) == 0) = []
Correction : The above wont remove both the duplicates
ind = diff([y{:}]) == 0;
y([ind 0] | [0 ind]) = []
BTW, this works even if there are multiple duplicate sequences
eg,
y = { 'd' 'f' 'a' 'g' 'g' 'w' 'a' 'h' 'h'};
ind = diff([y{:}]) == 0;
y([ind 0] | [0 ind]) = []
y =
'd' 'f' 'a' 'w' 'a'

Related

RSA Algorithm - don't want to find 'd'

Is there any 'p' ,'q' and 'e' that can't find any 'd' for it?
for example with this parameters:
q=13 , p=7 , e=25
we can find d=49 for it with this:
(e * d) % (12 * 6) = 1
but i want 'p', 'q' and 'e' that no 'd' can find for it...
is it possible or not?

Create an index to table

I have a table T as below:
T = table({'A';'A';'B';'B';'B';'B';'C';'C';'D';'D'},...
{'xd';'z';'x';'y';'z';'w';'x';'wh';'z';'w'},...
[4;2;4;1;2;5;2;1;1;5], ...
'VariableNames', {'memberId', 'productId','Rating'});
T =
memberId productId Rating
________ _________ ______
'A' 'xd' 4
'A' 'z' 2
'B' 'x' 4
'B' 'y' 1
'B' 'z' 2
'B' 'w' 5
'C' 'x' 2
'C' 'wh' 1
'D' 'z' 1
'D' 'w' 5
I need to index it by memberId and productId so the result is:
A: {'xd' 'z'}
B: {'x' 'y' 'z' 'w'}
C: {'x' 'wh'}
.......
You can use categorical arrays and a structure to do this:
% convert to categorical arrays
T.memberId = categorical(T.memberId);
T.productId = categorical(T.productId);
% cross-tabulate memberId vs. productId
cross_T = crosstab(T.memberId,T.productId);
% a function to return the productId for all 1 in row
productId = categories(T.productId).';
row = #(x) productId(logical(cross_T(x,:)));
% preform on all rows
rBy_c = arrayfun(row,1:size(cross_T,1),'UniformOutput',false).';
% convert to structure for readability
s = cell2struct(rBy_c,categories(T.memberId))
To get the output (s):
A: {'xd' 'z'}
B: {'w' 'x' 'y' 'z'}
C: {'wh' 'x'}
D: {'w' 'z'}

Replacing string with empty vector

I'm trying to modify this code so that if the input of this function contains the letter 'Z', it will return return an empty vector. I am able to do this for the letter 'Q' or 'Z' if it is at the beginning of string, but unfortunately it won't work if either of these two letters are at the end.
function d = change(a)
new_claim = regexprep(a, 'A', '2');
new_claim1 = regexprep(new_claim, 'B', '2');
new_claim2 = regexprep(new_claim1, 'C', '2');
new_claim3 = regexprep(new_claim2, 'D', '3');
new_claim4 = regexprep(new_claim3, 'E', '3');
new_claim5 = regexprep(new_claim4, 'F', '3');
new_claim6 = regexprep(new_claim5, 'G', '4');
new_claim7 = regexprep(new_claim6, 'H', '4');
new_claim8 = regexprep(new_claim7, 'I', '4');
new_claim9 = regexprep(new_claim8, 'J', '5');
new_claim10 = regexprep(new_claim9, 'K', '5');
new_claim11 = regexprep(new_claim10, 'L', '5');
new_claim12 = regexprep(new_claim11, 'M', '6');
new_claim13 = regexprep(new_claim12, 'N', '6');
new_claim14 = regexprep(new_claim13, 'O', '6');
new_claim15 = regexprep(new_claim14, 'P', '7');
new_claim16 = regexprep(new_claim15, 'R', '7');
new_claim17 = regexprep(new_claim16, 'S', '7');
new_claim18 = regexprep(new_claim17, 'T', '8');
new_claim19 = regexprep(new_claim18, 'U', '8');
new_claim20 = regexprep(new_claim19, 'V', '8');
new_claim21 = regexprep(new_claim20, 'W', '9');
new_claim22 = regexprep(new_claim21, 'X', '9');
new_claim23 = regexprep(new_claim22, 'Y', '9');
new_claim24 = regexprep(new_claim23, '-', ' ');
new_claim25 = regexprep(new_claim24, '(', '');
new_claim26 = regexprep(new_claim25, ')','');
d = new_claim26;
if strfind(d,'Q') == true
d = [];
elseif strfind(d,'Z') == true
d = [];
else
return;
end
If it's your desire to check to see if a string contains the letter Z or z, maybe put this at the beginning of your code:
if ~isempty(regexp(a, '[Zz]'))
d = [];
return;
end
If you also wanted to check for Q or q, you can do:
if ~isempty(regexp(a, '[ZzQq]'))
d = [];
return;
end
The above uses a regular expression to see if there are any characters in your string that contain either Z or z (or Q or q, depending on what you want). regexp returns the indices of where these characters were found. If there were Z or z (or Q or q characters, depending on what you want) characters found, then the indices would be non-empty, hence the ~isempty check. If there were no Z or z (or Q or q) characters that were found, this would be empty and so this statement is skipped. What's important is that if we have found Z, z (or Q, q) characters, we immediately make d empty and return so that the rest of the logic is not run.
You can then carry on with the rest of your code.
You can check if a character is in a string with: any(d == 'Q') || any(d == 'Z')

Deleting rows with specific rules

I got a 20*3 cell array and I need to delete the rows contains "137", "2" and "n:T"
Origin data:
'T' '' ''
'NP(*)' '' ''
[ 137] '' ''
[ 2] '' ''
'ARE' 'and' 'NP(FCC_A1#1)'
'' '' '1:T'
[ 1200] [0.7052] ''
[1.2051e+03] [0.7076] ''
'ARE' 'and' 'NP(FCC_A1#3)'
'' '' '2:T'
[ 1200] [0.0673] ''
[1.2051e+03] [0.0671] ''
'ARE' 'and' 'NP(M23C6)'
'' '' '3:T'
[ 1200] [0.2275] ''
[1.2051e+03] [0.2253] ''
[ 137] '' ''
[ 2] '' ''
And I want it to be like
'T' '' ''
'NP(*)' '' ''
'ARE' 'and' 'NP(FCC_A1#1)'
[ 1200] [0.7052] ''
[1.2051e+03] [0.7076] ''
'ARE' 'and' 'NP(FCC_A1#3)'
[ 1200] [0.0673] ''
[1.2051e+03] [0.0671] ''
'ARE' 'and' 'NP(M23C6)'
[ 1200] [0.2275] ''
[1.2051e+03] [0.2253] ''
I've tried regexp and strcmp and they don't work well. Plus the cell array also hard to deal with. Can anyone help?
Thank you in advance.
If you can somehow read your original data so that all cells are strings or empty arrays (not numeric values), you can do it with strcmp and regexprep:
% The variable 'data' is a 2D-cell array of strings or empty arrays
datarep = regexprep(data,'^\d+:T','2'); % replace 'n:T' with '2' for convenience
remove1 = strcmp('2',datarep); % this takes care of '2' and 'n:T'
remove2 = strcmp('137',datarep); % this takes care of '137'
rows_keep = find(~sum(remove1|remove2,2)); % rows that will be kept
solution = data(rows_keep,:)
For example, with this data
'aa' 'bb' 'cc'
'dd' 'dd' '2'
'137' 'dd' 'dd'
'dd' 'dd' '11:T'
'1:T' '1:137' 'dd'
'dd' '' []
the result in the variable solution is
'aa' 'bb' 'cc'
'dd' '' []
I just tried the following codes on my desktop and it seems to do the trick. I made a as the cell array you had.
L = size(a, 1);
mask = false(L, 1);
for ii = 1:L
if isnumeric(a{ii, 1}) && (a{ii, 1} == 137 || a{ii, 1} == 2)
mask(ii) = true;
elseif ~isempty(a{ii, 3}) && strcmp(a{ii, 3}(end-1:end), ':T')
mask(ii) = true;
end
end
b = a(~mask, :)
Now, b should be the cell array you wanted. Basically, I created a logical mask that indicates the position of rows that satisfy the rules, then use the inverse of it to call out the rows.
Here is another simple option:
%Anonymous function that checks if a cell is equal to 173 or to 2 or fits the '*:T*' pattern
Eq137or2 = #(x) sum(x == 137 | x == 2) | sum(strfind(num2str(x), ':T') > 1)
%Use the anonymous functions to find the rows you don't want
mask = = sum(cellfun(Eq137or2, a),2)
%Remove the unwanted rows
a(~mask, :)

User input initials - ImpactJS

So on my end state I want to have the user input their initials. I have setup an array that has all the alphabet, triggers to select a letter and font_draw, but I cant seem but I get an error saying my function is not defined. Any ideas?
userInitials: function(){
io_clear();
a = 0
l[0] = " "
l[1] = "a"
l[2] = 'b'
l[3] = 'c'
l[4] = 'd'
l[5] = 'e'
l[6] = 'f'
l[7] = 'g'
l[8] = 'h'
l[9] = 'i'
l[10] = 'j'
l[11] = 'k'
l[12] = 'l'
l[13] = 'm'
l[14] = 'n'
l[15] = 'o'
l[16] = 'p'
l[17] = 'q'
l[18] = 'r'
l[19] = 's'
l[20] = 't'
l[21] = 'u'
l[22] = 'v'
l[23] = 'w'
l[24] = 'x'
l[25] = 'y'
l[26] = 'z'
str = ""
if(ig.input.pressed('up')){
if (a>26){
a+= 1;
}else{
a = 0;
}
}
if(ig.input.pressed('down')){
if (a<0){
a -= 1;
}else{
a = 26;
}
}
this.font_draw(x,y,str+'['+1[a]+'] ');
if(ig.input.pressed('space')){
str += l[a];
}
},
draw:function(){
if(this.gameOver){
this.font.draw(userInitials, ig.system.width/2, 95, ig.Font.ALIGN.CENTER);
}
When you're calling functions you want to use 'this'.
If there's no current object, 'this' refers to the global object. In a web browser, that’s ‘window’ — the top-level object, which represents the document, location, history and a few other useful properties and methods.
‘this’ remains the global object if you’re calling a function:
So therefore, this.userInitials() will work:
this.font.draw(this.userInitials(), ig.system.width/2, 95, ig.Font.ALIGN.CENTER);