Reputation: 149
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
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
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
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