Векторизованные операции над массивами ячеек - PullRequest
8 голосов
/ 28 июня 2011

Это сообщение было вызвано после обсуждения о том, являются ли массивы ячеек "нормальными массивами" и что векторизация не работает для массивов ячеек.

Интересно, почему следующий синтаксис векторизации не реализованв MATLAB, что говорит против этого:

>> {'hallo','matlab','world'} == 'matlab'
??? Undefined function or method 'eq' for input arguments of type 'cell'.

внутренне это будет эквивалентно

[{'hallo'},{'matlab'},{'world'}] == {'matlab'}

, потому что MATLAB знает, когда разыграть, следующие работы:

[{'hallo','matlab'},'world']

Массив ячеек Массив указателей .Если и левая, и правая стороны указывают на равные объекты, isequal('hallo','hallo') возвращает ожидаемое значение true, тогда почему MATLAB по-прежнему не допускает самый верхний пример?

Я знаю Я могу использовать strmatch илиcellfun.

РЕЗЮМЕ :

  • Оператор ==, который требуется для векторизации в приведенном выше примере, равен eq, а не isequal (прочееоператоры: <, то есть lt и т. д.)
  • eq встроено для числовых типов, для всех других типов (например, для строк) MATLAB дает свободу перегрузки этого (и других)операторы.
  • оператор векторизации, таким образом, вполне возможен с массивами ячеек определенного типа (например, строки), но не по умолчанию для любого типа.
  • функция векторизации, такая как myFun( myString ) или myFun( myCellOfStrings ),также возможно, вы просто должны реализовать это внутри myFun.Функции sin(val) и sin(array) работают также не колдовством, а потому, что оба случая реализованы внутри.

Ответы [ 4 ]

6 голосов
/ 28 июня 2011

Во-первых, == - это , а не - это то же самое, что isequal. Функция, которая вызывается при использовании ==, равна eq, и область действия каждого из них различна.

Например, в eq(A,B), если B является скаляром, функция проверяет каждый элемент A на равенство с B и возвращает логический вектор.

eq([2,5,4,2],2)

ans =

     1     0     0     1

Тем не менее, isequal(A,B) проверяет, является ли A равным равным B во всех аспектах. Другими словами, MATLAB не может определить разницу между A и B. Делаем это для приведенного выше примера:

isequal([2,5,4,2],2)

ans =

     0

Я думаю, что вы действительно намеревались задать в вопросе, но не ответили:

"Почему == не определено для массивов ячеек?"

Ну, простая причина в том, что клетки не были предназначены для такого использования. Вы можете легко увидеть, как реализация такой функции для ячеек может быстро усложниться, если вы начнете рассматривать отдельные случаи. Например, рассмотрим

{2,5,{4,2}}==2

Каким вы ожидаете получить ответ? Разумное предположение будет

ans = {1,0,0}

что справедливо. Но скажем, я не согласен. Теперь я хотел бы, чтобы операция равенства прошла по вложенным ячейкам и вернула

ans = {1,0,{0,1}}

Можете ли вы не согласиться с этой интерпретацией? Возможно нет. Это в равной степени верно, а в некоторых случаях это поведение, которое вы хотите.

Это был просто простой пример. Теперь добавьте к этому смесь вложенных ячеек, разных типов и т. Д. Внутри ячейки и подумайте над обработкой каждого из этих угловых случаев. Для разработчиков быстро становится кошмаром реализовать такую ​​функциональность, которая может быть удовлетворительно использована всеми .

Таким образом, решение состоит в том, чтобы перегрузить функцию, реализуя только те специальные функции, которые вы желаете использовать в вашем приложении. MATLAB также предоставляет способ сделать это, создав каталог @cell и определив eq.m для использования с ячейками так, как вам нужно 1061 *. Рамашаланка продемонстрировал это в своем ответе .

4 голосов
/ 28 июня 2011

Есть много вещей, которые для MATLAB могут показаться естественными, которые они решили не делать.Возможно, они не хотят рассматривать много особых случаев (см. Ниже).Вы можете сделать это самостоятельно, перегружая.Если вы создадите каталог @cell и добавите в новую функцию следующее: eq.m:

function c = eq(a,b)
if iscell(b) && ~iscell(a)
    c = eq(b,a);
else
    c = cell(size(a));
    for n = 1:numel(c)
        if iscell(a) && iscell(b)
            c{n} = isequal(a{n},b{n});
        else
            c{n} = isequal(a{n},b);
        end
    end
end

Тогда вы можете сделать, например:

>> {'hallo','matlab','world'} == 'matlab'
ans =     [0]    [1]    [0]

>> {'hallo','matlab','world'} == {'a','matlab','b'}
ans =     [0]    [1]    [0]

>> {'hallo','matlab','world'} == {'a','dd','matlab'}
ans =     [0]    [0]    [0]

>>  { 1, 2, 3 } == 2
ans =     [0]    [1]    [0]

Но даже если яЯ рассмотрел пару случаев в моей простой функции, но я не учел много вещей (проверка ячеек одинакового размера, проверка многоэлементной ячейки на одноэлементный и т. д. и т. д.).

Я использовал isequal, хотя он вызывается с eq (то есть ==), поскольку он обрабатывает {'hallo','matlab','world'} == 'matlab' лучше, но на самом деле я должен рассмотреть больше случаев.

(РЕДАКТИРОВАТЬ: Iсделал функцию немного короче, но менее эффективной)

1 голос
/ 28 июня 2011

Причина этой проблемы: массивы ячеек могут хранить разные типы переменных в разных ячейках.Таким образом, оператор == не может быть определен хорошо для всего массива.Возможно даже, что ячейка содержит другую ячейку, что еще больше усугубляет проблему.

Подумайте о {4,'4',4.0,{4,4,4}} == '4'.какой должен быть результат?Каждый тип оценивается по-разному.

1 голос
/ 28 июня 2011

Это не уникально для строк. Даже следующее не работает:

{ 1, 2, 3 } == 2

Массивы ячеек не совпадают с «обычными» массивами: они предлагают разный синтаксис, разную семантику, разные возможности и реализованы по-разному (дополнительный уровень косвенности).

Рассмотрим, был ли == для массивов ячеек определен в терминах isequal для каждого элемента. Таким образом, приведенный выше пример не будет проблемой. Но как насчет этого?

{ [1 0 1], [1 1 0] } == 1

Получившееся поведение было бы ужасно полезным в большинстве случаев. А что по этому поводу?

1 == { 1, 2, 3 }

И как бы вы это определили? (Я могу придумать как минимум три разные интерпретации.)

{ 1, 2, 3 } == { 4, 5, 6 }

А что по этому поводу?

{ 1, 2, 3 } == { { 4, 5, 6 } }

или это?

{ 1, 2, 3 } == { 4; 5; 6 }

или это?

{ 1, 2, 3 } == { 4, 5 }

Вы можете добавить все виды обработки в особых случаях, но это делает язык менее согласованным, более сложным и менее предсказуемым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...