2016-06-29 5 views
1

Рассмотрим следующую функцию, где входы являютсяПризнавая вклад клеток в одной строке

>> b.a = 1  
b =  
    a: 1 

>> c = {'this' 'cell'}  
c =  
    'this' 'cell' 

>> d = [1 2 3]  
d =  
    1  2  3 

вход может быть вызван разными способами, например testfunction(b,d,c)testfunction(d,c,b) и т.д. Я хочу, чтобы получить входной ячейки и получить некоторые данные из него

function testfunction(varargin) 
for i =1:numel(varargin) 
    if(iscell(varargin{i})) 
     fprintf('The input number %d is a cell!\n',i) 
    end 
end 

который распознает, является ли переменный ввод ячейкой, но существует ли какой-либо изящный способ сделать это? потому что iscell оленья кожа вернется обратно индекс, я также использовал class() но он возвращает класс varargin вместо ввода

ответ

2

Основная проблема здесь - не производительность, а читаемость и наличие довольно кода.

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

Пример функции:

function idx = cell_index(C) 
idx = 0; 
if isempty(C) 
    warning('No input was given.') 
else 
    for ii = 1:numel(C) 
     if(iscell(C{ii})) 
      idx = ii; 
     end 
    end 
end 
if idx == 0 
    warning('The input contained no cells.')   
end 
end 

Теперь вы можете сделать следующее в своей основной функции:

function output = main_function(varargin) 
    idx = cell_index(varargin) 
    fprintf('The input number %d is a cell!\n', idx) 
    % 
    % or fprintf('The input number %d is a cell!\n, cell_index(varargin)) 

% Rest of code 

** Loops по сравнению с другими подходами: **

Давайте опробуем несколько функции:

Appraoach 1: Loop

Это самый быстрый один:

function s = testfunction1(varargin)  
for ii = 1:numel(varargin) 
    if(iscell(varargin{ii})) 
     s = sprintf('The input %i is a cell!\n', ii); 
    end 
end 
end 

подход 2: cellfun

Это самый медленный и самый тяжелый для чтения (IMO):

function s = testfunction2(varargin)  
if any(cellfun(@(x) iscell(x),varargin)) 
    s = sprintf('The input %s is a cell\n', num2str(find(cellfun(@(x) iscell(x),varargin)))); 
end  
end 

подход 3: cellfun

Это самый простой, если вы не хотите петли

function s = testfunction3(varargin)  
x = find(cellfun(@(x) iscell(x),varargin)); 
if ~isempty(x) 
    s = sprintf('The input %i is a cell \n',x); 
end  
end 

Следующая эталонное тестирование проводится с использованием Matlab R2014b, перед новым JIT двигателя!

f = @() testfunction1(b,c,d); 
g = @() testfunction2(b,c,d); 
h = @() testfunction3(b,c,d); 
timeit(f) 
ans = 
    5.1292e-05 

timeit(g) 
ans = 
    2.0464e-04 

timeit(h) 
ans = 
    9.7879e-05 

Резюме:

Если вы хотите использовать подход без петель, я предлагаю последний подход (второй cellfun версии). Это выполняет только один find и один звонок до cellfun. Поэтому его легче читать, и это быстрее.

+0

Griffen: Привет, я с радостью приму ваш ответ, но я уже знал о «cellfun», который также является функцией-оболочкой для цикла. Я просто хотел узнать, есть ли способ получить индекс от функции, как 'ismember', может быть, я не смог правильно объяснить свой вопрос – Umar

1

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

testfunction(b,c,d) 
testfunction(b,c,d,c) 
testfunction(b,d) 


function testfunction(varargin) 

if any(cellfun(@(x) iscell(x),varargin)) 
fprintf(['The input(s) ' num2str(find(cellfun(@(x) iscell(x),varargin))) ' is (are) cell \n']); 
end 

end 
+0

cellfun - это функция-обертка для цикла for any :) +1 – Umar

+0

ну да, но это «распознавание ввода ячейки в одну строку» :). Но я получаю вашу мысль, и я попробую еще раз. Всегда ли есть 3 входа? – Finn

+0

Нет количества входов может быть даже 100, но одна из них - ячейка – Umar