Why is an empty string not empty? isempty('') returns true, but isempty("") returns false

88 Ansichten (letzte 30 Tage)
(Updated to clarify the problem)
Strings, added in R2016b, are a great addition to matlab, but one aspect is a problem: testing for empty variables with isempty() no longer gives a consistent response.
>> isempty('')
ans =
logical
1
>> isempty("")
ans =
logical
0
% even though comparison for equality is 'true':
>> '' == ""
ans =
logical
1
One would expect that if the two values are considered equal, that a builtin function like isempty() would produce the same result.
Presumably "" is not empty because it is a string object, while '' really is the same as [ ]. But this is a problem for code that tests for empty character input using isempty(...). It no longer works as expected if passed "" instead of ''. Is there a switch we can turn on or off to enable isempty("") to return true?
A function written prior to R2016b never needed to check for empty "" (double-quoted) strings, because Matlab would throw an exception if passed something in double quotes. Now, that code produces incorrect results if a user passes in an empty double-quoted string.
One can, of course, test using strlength(...)==0, but IIRC, the Matlab IDE gave a warning about efficiency for this, and recommended using isempty(...).
  4 Kommentare
Stephen23
Stephen23 am 19 Jan. 2018
Bearbeitet: Stephen23 am 19 Jan. 2018
" The problem is that code written prior to R2016b never had to test for input of "" "
The solution is not to create a totally misleading and inconsistent definition of empty. You need to bite the bullet and update your code. And probably improve the input checking to make sure that it only works with data types that work properly.
Star Strider
Star Strider am 19 Jan. 2018
See if the anonymous function in my Comment does what you want.

Melden Sie sich an, um zu kommentieren.

Antworten (6)

Kelly Kearney
Kelly Kearney am 19 Jan. 2018
I think string arrays function more like cell arrays in this context... the first element of the string itself isn't empty, but the contents of that element are:
>> y = "";
>> whos y
Name Size Bytes Class Attributes
y 1x1 132 string
>> isempty(y)
ans =
logical
0
>> isempty(y{1})
ans =
logical
1
  4 Kommentare
Ian
Ian am 19 Jan. 2018
Hmmm. That would work, unless x is potentially an array of strings. In that case the conversion needs to be to a cell array of chars.
if true
if isstring(x)
if (length(x) == 1)
x = char(x);
else
x = cellstr(x);
end
end
endan array of chars.
Stephen23
Stephen23 am 19 Jan. 2018
Bearbeitet: Stephen23 am 19 Jan. 2018
"The problem is that existing code which checks for empty strings using isempty(...) no longer works correctly if a user passes it an empty string (in double quotes) instead of a char array (in single quotes)"
That isn't a "problem" at all, because that is actually the correct behavior: a scalar string is a scalar string, no matter how many characters it might contain.
"no longer works correctly"
MATLAB works correctly. What you are proposing is totally inconsistent, as the size of a string array is totally unrelated to how many characters might be contained in any one element of that array. That is in fact the whole point of string arrays.

Melden Sie sich an, um zu kommentieren.


Star Strider
Star Strider am 19 Jan. 2018
Another option is the strlength (link) function. It appears to give the correct results for both string and character arrays:
chr1 = '';
chr2 = 'ab';
str1 = "";
str2 = "ab";
lenstr1 = strlength(str1)
lenstr2 = strlength(str2)
lenchr1 = strlength(chr1)
lenchr2 = strlength(chr2)
lenstr1 =
0
lenstr2 =
2
lenchr1 =
0
lenchr2 =
2
so there is no need to test the variable type, only the length.
  3 Kommentare
Star Strider
Star Strider am 19 Jan. 2018
You could use isnumeric to test for numeric variables (including the empty array [] that returns true), and if that returns false, then test with strlength.
Experiment with this anonymous function with various arguments:
mtstr = @(x) ~isnumeric(x) && (strlength(x) == 0);
The ‘&&’ short-circuits the function so strlength will not ‘see’ numeric inputs.
Stephen23
Stephen23 am 19 Jan. 2018
" I'm trying to find a clean solution that avoids going back through thousands of lines of code written prior to R2016b and rewriting all my tests for empty strings."
You need to accept that different MATLAB versions have different features and can behave in different ways. You can either pick one version and stick with it, or accept that newer versions made some changes and ensure that your code matches that. The decision is yours. (This applies to all languages of course, not just MATLAB)
Your proposal of creating a totally inconsistent definition of empty is certainly not a "clean solution".

Melden Sie sich an, um zu kommentieren.


Ian
Ian am 19 Jan. 2018
Hmmm. I suppose one could override isempty(...) Attempting to view the code for isempty(), it shows no code, just comments, that says isempty() is a builtin, but suggests the equivialent is:
prod(size(x))==0
The following should do the trick, if placed in the searchpath before the matlab folders are searched. Then none of my code needs to be updated...just put that in my utils folder. Unfortunately, it produces a long string of warnings.:
function tf = isempty(x)
if (isstring(x))
tf = strlength(x)==0;
else
tf = prod(size(x));
end
end
  5 Kommentare
Ian
Ian am 19 Jan. 2018
the use of isempty(...) to test for empty strings
Stephen23
Stephen23 am 20 Jan. 2018
Bearbeitet: Stephen23 am 20 Jan. 2018
What has been deprecated?
"the use of isempty(...) to test for empty strings"
No, isempty correctly tests for empty strings, exactly as it should. It certainly has not been deprecated. A 2x1 string is NOT empty, a 1x1 string is NOT empty (no matter how many characters it contains), and a 1x0 string is empty. Try it:
isempty(strings(1,0)) % a 1x0 string really is empty!
What you are claiming is that
strings(1,1) % scalar string with no characters
should be classified as empty. Under your inconsistent definition of empty (where 1x1 string with zero characters is empty) this 1x4 string array would cause four iterations of this loop:
S = ["ABC","DEF","GHI","JK"] % 1x4 string array
while ~isempty(S), S=S(2:end), end
whereas this 1x4 string array would iterate three times:
S = ["ABC","DEF","GHI",""] % 1x4 string array
while ~isempty(S), S=S(2:end), end
and apparently this would not iterate even once!:
S = ["","","",""] % 1x4 string array.
while ~isempty(S), S=S(2:end), end
Even though all of them are 1x4 string arrays, you have just invented a definition of empty that magically changes how many times my loop iterates, not depending on the size of the array itself (which is what MATLAB currently does) but depending on the number of characters within the string array. If you then decide that a 1x4 string array should obviously cause it to iterate four times, then how many times should it for a 1x3 string? Or a 1x2 string? Or a 1x1 string? Or a 1x0 string?
Oh... Actually I think I like this more and more: I could use this to avoid doing lots of work: "sorry I could not process your data: you entered the test name as an empty string and as a result my code just skipped that iteration entirely, and so I never knew about it". You have me convinced!
Nothing has been deprecated. isempty is totally correct.
PS: actually I could not figure out how many iterations this string array ["","","",""] would result in using your inconsistent definition of isempty:
  • four times? (disagrees with you insisting that 1x1 can be empty)
  • three times? (because only the last iteration would be a 1x1 string with zero characters, fitting your definition).
  • zero times? (because all four of the string elements have zero characters).
Three times seems to fit your definition, but would mean that that loop runs a different number of times depending on what data is contained in the string, and not on the size of the string itself! So in some cases your definition causes my 1x4 string to be iterated over four times, sometimes maybe three times... and I cannot use size or numel to tell me!
Oh, if only MATLAB had implemented some consistent definition of isempty, so that my loop always iterated over all of my 1x4 arrays (not matter what class) consistently four times! Oh wait... that is exactly what MATLAB already does!
PPS: What about ["","","","ABC"]? Your special isempty definition has me totally flummoxed on this one. Please advise how it would work!

Melden Sie sich an, um zu kommentieren.


Ian
Ian am 19 Jan. 2018
Bearbeitet: Ian am 19 Jan. 2018
There have been many good suggestions above for workarounds for code going forward. Thanks all for your input. Having read and synthesized everyone's input, here are my (hopefully final) thoughts.
First, it seems that there are no perfect solutions here. On one hand, Cobeldick is right that changing isempty("") to return true would produce problems for someone who needs "" to not be empty; on the other hand, there is a huge codebase out there, including mine, which tests for empty strings with isempty(...) and which did not anticipate the introduction into matlab of string objects for which isempty("") would return false. That code base now is broken, and I and many others now need to update our code.
For my own part, I am going back through all my code and replacing all calls to isempty(...) with a call to a new function that returns the proper answer for my needs, and putting that function in a folder which is in the search path for all code I write.
In case it helps others, here is that function:
function tf = isempty_s(x)
tf = isempty(x) || (isstring(x) && length(x) == 1 && strlength(x)==0);
end
  10 Kommentare
Walter Roberson
Walter Roberson am 20 Jan. 2018
Mathworks uses
matlab.io.internal.utility.convertStringsToChars
to do the conversion on argument lists. That is, you can use
[varargin{:}] = matlab.io.internal.utility.convertStringsToChars(varargin{:});
Brian Kim
Brian Kim am 28 Apr. 2021
You can also do
xChar = convertStringsToChars(x);
tf = isempty(xChar);

Melden Sie sich an, um zu kommentieren.


Jim Riggs
Jim Riggs am 19 Jan. 2018
As near as I can tell, Matlab does not use the double quote character, so
isempty("")
is not a valid statement.
  5 Kommentare
Walter Roberson
Walter Roberson am 20 Jan. 2018
The use of double quotes on input was introduced in R2017a, but string objects were introduced in R2016b.

Melden Sie sich an, um zu kommentieren.


Ian
Ian am 19 Jan. 2018
I think I'm going to submit this to MathWorks as a bug, and see what they say.
  6 Kommentare
Ian
Ian am 19 Jan. 2018
Thanks for your comments. I appreciate your attempt to help me.
Please see my "accepted answer" above.
Note, BTW, that matlab considers "" and '' to be equal:
>> "" == ''
ans =
logical
1
Therefore I would not say that it is unreasonable to expect a builtin function like isempty(...) to produce identical results for the two inputs.
This is an unfortunate unintended consequence of the late introduction of strings to the matlab programming language, for which there is probably no good resolution.
Stephen23
Stephen23 am 20 Jan. 2018
Bearbeitet: Stephen23 am 20 Jan. 2018
"Note, BTW, that matlab considers "" and '' to be equal:"
"Therefore I would not say that it is unreasonable to expect a builtin function like isempty(...) to produce identical results for the two inputs."
eq for strings is very much an overloaded convenience operator, as the help describes: "If one input is a string array, the other input can be a string array, a character vector, or a cell array of character vectors. The corresponding elements of A and B are compared lexicographically".
Lexicographical equivalence does not imply that any of these different arrays are in any other ways identical.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Characters and Strings finden Sie in Help Center und File Exchange

Produkte

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by