【问题标题】:How do I zip multiple cell arrays together?如何将多个单元阵列压缩在一起?
【发布时间】:2014-10-02 17:11:07
【问题描述】:

在许多其他语言中,将多个列表压缩在一起意味着采取类似的方式

((x1, x2, x3, x4), (y1, y2, y3, y3))

把它变成

((x1, y1), (x2, y2), (x3, y3), (x4, y4))

这当然适用于列表

  • 有超过 2 个子列表,
  • 其子列表的长度不是 4,并且
  • 其子列表的长度可能完全不同。

我发现自己经常这样做,所以我想我会分享解决方案。

【问题讨论】:

标签: matlab cell-array


【解决方案1】:

这是我的实现:

function out = zipCells(varargin)
    % make sure all inputs are cell arrays
    assert(all(cellfun(@iscell, varargin)), 'Expecting cell arrays');

    % make them all of the same length
    mn = min(cellfun(@numel, varargin));
    in = cellfun(@(c) c(1:mn), varargin, 'UniformOutput',false);

    % zip lists
    out = cellfun(@(varargin) varargin, in{:}, 'UniformOutput',false);
end

(最后一行是使用comma-separated lists展开元胞数组in{:}的元胞数组)

例子:

>> c = zipCells({'x','y','z'}, {1,2}, {'a','b','c'})
c = 
    {1x3 cell}    {1x3 cell}
>> c{:}
ans = 
    'x'    [1]    'a'
ans = 
    'y'    [2]    'b'

【讨论】:

    【解决方案2】:
    1. 如果所有单元格都具有相同的长度,则有一个不带cellfun、arrayfun 或循环的简单解决方案。它基于mat2cell(尽管它的名称)可以应用于元胞数组这一事实:

      function out = zipCells(varargin)
      n = numel(varargin{1});
      out = mat2cell(reshape([varargin{:}], n, []), ones(1, n)).';
      
    2. 在一般情况下:将单元格修剪到最小长度(cellfun 的两次使用)并按上述方式进行:

      function out = zipCells(varargin)
      n = min(cellfun(@numel, varargin));
      varargin = cellfun(@(c) c(1:n), varargin, 'uniformoutput', 0);
      out = mat2cell(reshape([varargin{:}], n, []), ones(1, n)).';
      
    3. 允许输入具有不同方向的单元格(行/列)的扩展:

      function out = zipCells(varargin)
      n = min(cellfun(@numel, varargin));
      varargin = cellfun(@(c) reshape(c(1:n), 1,[]), varargin, 'uniformoutput', 0);
      out = mat2cell(reshape([varargin{:}], n, []), ones(1, n)).';
      

    【讨论】:

    • num2cell(.,2) 也可用于简化mat2cell(.,ones(1,n)) 调用
    • @Amro 奇怪的是,这些函数的名称并不能反映它们所能做的所有事情。我猜他们的功能被扩展了,但名字被保留了
    【解决方案3】:

    您当然可以将所有内容放在一起,但名称应该有助于描述正在发生的事情:

    function output = zipCells(varargin)
    
    numComponents = min(cellfun(@length, varargin));
    makeComponentI = @(i) cellfun(@(c) c{i}, varargin, 'UniformOutput', false);
    output = arrayfun(makeComponentI, 1:numComponents, 'UniformOutput', false);
    

    下面是实际操作:

    >> pairs = zipCells({'a' 'b' 'c' 'd'}, {1 2 3 4})
    pairs = 
        {1x2 cell}    {1x2 cell}    {1x2 cell}    {1x2 cell}
    >> pairs{:}
    ans = 
        'a'    [1]
    ans = 
        'b'    [2]
    ans = 
        'c'    [3]
    ans = 
        'd'    [4]
    

    希望这会有所帮助。

    【讨论】:

    • 超过时间限制后,考虑接受您的回答,向 StackOverflow 社区表明您不再需要任何帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-24
    • 1970-01-01
    • 2012-09-23
    • 2021-05-25
    相关资源
    最近更新 更多