NoetherNerd
NoetherNerd

Reputation: 149

Python zip function in Matlab

I have some Python code that I would like to run in Matlab. Suppose you have two lists of the same length:

    x = [0, 2, 2, 5, 8, 10]
    y = [0,2, 4, 7, 3, 3]

    P = np.copy(y)
    P.sort()
    P = np.unique(P, axis=0) # P = [0 2 3 4 7]  Takes the list y, sorts it and removes repeated elements

    s = list(zip(x,y))  #match list x with y: s = [(0, 0), (2, 2), (2, 4), (5, 7), (8, 3), (10, 3)]

    for y_1,y_2 in zip(P,P[1:]):  # runs over (0, 2), (2, 3), (3, 4), (4, 7)
        for v_1,v_2 in zip(s, s[1:]):
                -- process --

Where in this case:

list(zip(s, s[1:])) = [((0, 0), (2, 2)), ((2, 2), (2, 4)), ((2, 4), (5, 7)), ((5, 7), (8, 3)), ((8, 3), (10, 3))]

I would like to translate this in Matlab but I don't know how to replicate the zip function. Any ideas on how I can do this?

Upvotes: 4

Views: 1252

Answers (3)

OverLordGoldDragon
OverLordGoldDragon

Reputation: 19806

A zip list comprehension can be partially recreated via

ls0 = [1 2];
ls1 = [3 4];

g = [ls0; ls1]';
cellfun(@(x)[x(1)*0, x(2) + 1], {g(1,:), g(2,:)}, 'UniformOutput', false)
ans =

  1×2 cell array

    {[0 4]}    {[0 5]}

or, as a 1-liner (returning 2x2 matrix instead)

table2array(rowfun(@(x)[x(1)*0, x(2) + 1], table([ls0; ls1]')))

which in Python is

ls0, ls1 = [1, 2], [3, 4]
[(a*0, b + 1) for a, b in zip(ls0, ls1)]
[(0, 4), (0, 5)]

They're fair options for when inputs are small. If speed/memory is of concern, best to instead focus on MATLAB-efficient commands (beware of copies).

One could generalize this to any number of lists and comprehension logic (arbitrary function instead of *0) and introduce conditionals; I've done this for dictionary here.

Alternatives in other answers, and I especially like @AndrewJanke's comment (plain for-loop)

c = num2cell([ls0; ls1]');
for col = c
    [a, b] = col{:};
    disp([a, b])
end
     1     2

     3     4

Upvotes: 0

Andrew Janke
Andrew Janke

Reputation: 23888

Here's an implementation of Python's zip function in Matlab.

function out = zip(varargin)
% Emulate Python's zip() function.
%
% Don't actually use this! It will be slow. Matlab code works differently.
args = varargin;
nArgs = numel(args);
n = numel(args{1});
out = cell(1, n);
for i = 1:n
    blah = cell(1, nArgs);
    for j = 1:nArgs
        if iscell(args{j})
            blah(j) = args{j}(i);
        else
            blah{j} = args{j}(i);
        end
    end
    out{i} = blah;
end
end

But don't use it; the performance will be lousy. In Matlab, you want to keep things in parallel primitive arrays instead, and use vectorized operations on those. Or, if you have to, iterate over array indexes.

Upvotes: 1

Cris Luengo
Cris Luengo

Reputation: 60660

MATLAB doesn’t have a zip, but you can accomplish the same thing in various ways. I think that the simplest translation of


for y_1,y_2 in zip(P,P[1:]):
   ...

is

for ii = 1:numel(P)-1
   y_1 = P(ii);
   y_2 = P(ii+1);
   ...

And in general, iterating over zip(x,y) is accomplished by iterating over indices 1:numel(x), then using the loop index to index into the arrays x and y.

Upvotes: 2

Related Questions