Is there a smart way grab Values from a 2d Array in Pairs and additionally to that the last number in the row?

My Data (saved in a file) look something similar to this:

  0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3  

After loading this Data into Matlab I need to group up the Data into Tuples by always taking the Pairs. In this Example it would be:

[0,89],[27,100],[42,75],[0,100],...[100,19]

After the pairing the Data (or meanwhile), I need to add the last Number in the row to the Pairs. The Previous mentioned Data would be altered followingly:

[0,89,8],[27,100,8],[42,75,8],[0,100,6],...[100,19,3]

How would be a smart way to solve this? I personally dislike the extensive use of Loops and think there is a nicer Solution.

有帮助吗?

解决方案

Edit: This should do the trick.

M=[0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3]

X = M(:,1:end-1)
Y = M(:,end)
idxOdd = mod(1:size(X,2),2)==1
Xeven=X(:,~idxOdd)
Xodd=X(:,idxOdd)

Yrep = repmat(Y,1,sum(idxOdd))

[Xodd(:) Xeven(:) Yrep(:)]

其他提示

I think it's amazing no-one has come up with this one:

M = [   
  0  89  27 100  42  75 8  
  0 100   7  92   5  68 6  
  0  67  49  83 100 100 2  
 35  76  57 100 100  92 5  
 18  68  50  54 100  19 3  ];


C = arrayfun(...
    @(ii) [M(:,ii:ii+1) M(:,end)], ...
    1:2:size(M,2)-1, 'UniformOuput', false);

You'll end up with this cell array:

>> C{1}

ans =

     0    89     8
     0   100     6
     0    67     2
    35    76     5
    18    68     3

>> C{2}

ans =

    27   100     8
     7    92     6
    49    83     2
    57   100     5
    50    54     3

>> C{3}

ans =

    42    75     8
     5    68     6
   100   100     2
   100    92     5
   100    19     3

Now you can refer to individual tuples like so:

C{1}(2,:)   %  [  0   100   6]
C{3}(4,:)   %  [100    92   5]

This can be done using logical indexing. Building off of Dennis's answer:

z = M(:,end); %# extract the last column
M = M(:,1:end-1); %# chop off the last column from the rest of your data
xidx = logical(mod(1:size(M,2),2)); %# get a logical index of the odd numbered rows
x = M(:,xidx); %# grab the x values
y = M(:,~xidx); %# grab the y values
z = repmat(z,1,numel(x)/numel(z)); % replicate z to match numel of x and y
x = reshape(x',numel(x),1);    %# reshape the arrays to form the right dimensions
y = reshape(y',numel(y),1);
z = reshape(z',numel(z),1);
output = [x,y,z]; %# format output

For grouping the data in matrix A, you can use cell2mat and output an array of cell tuples C, then append last column elements in corresponding lines in this array:

% separate the data pairs
C = mat2cell(A(:,1:end-1), ones(1,size(A,1)), 2*ones(1,3));

% single for-loop to append line_lat_element in cells of same row
for i = 1:size(A,1)
    D(i,:) = cellfun(@(x) [x A(i,end)], {C{i,:}}, 'UniformOutput', false);
end

As output, each D{i,j} entry of the cell array will contain the triplet [data1 data2 last_element_of_line].

I would like to defend the humble for loop in this case:

M = [  0  89  27 100  42  75 8  ;
         0 100   7  92   5  68 6  ;
         0  67  49  83 100 100 2  ;
        35  76  57 100 100  92 5  ;
        18  68  50  54 100  19 3 ];

out = zeros((size(M,2)-1)/2*size(M,1),3);
ind = 1;
for row = 1:size(M,1)
    for col = 1:2:(size(M,2)-1)
        out(ind,:) = [M(row,col:col+1) M(row,end)];
        ind = ind+1;
    end
end
out

I claim that this is easier to write, understand and maintain than the non-loop versions (either for a programmer new to the code, or the same programmer returning to the code weeks, months, or years later). The only slightly-tricky part is calculating the proper size for the output matrix out. If performance becomes an issue, then sure, look at a non-loop version. But recent versions of MATLAB run for loops much faster than in the past, so why optimize prematurely?

You could eliminate the need to keep a running index by a clever calculation based on row and col, but why bother? The above code is simple and easy for a programmer to understand

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top