سؤال

هذا السؤال لديه بالفعل إجابة هنا:

سؤالي مشابه لهذا واحد, ، لكنني أود تكرار كل عنصر وفقًا لعدد محدد في صفيف ثانٍ من نفس الحجم.

مثال على ذلك ، قل أن لدي صفيف v = [3 1 9 4], ، أريد أن استخدام rep = [2 3 1 5] لتكرار العنصر الأول مرتين ، والثاني ثلاث مرات ، وما إلى ذلك للحصول على [3 3 1 1 1 9 4 4 4 4 4].

حتى الآن أستخدم حلقة بسيطة لإنجاز المهمة. هذا ما بدأت به:

vv = [];
for i=1:numel(v)
    vv = [vv repmat(v(i),1,rep(i))];
end

تمكنت من التحسن عن طريق تسليح الفضاء:

vv = zeros(1,sum(rep));
c = cumsum([1 rep]);
for i=1:numel(v)
    vv(c(i):c(i)+rep(i)-1) = repmat(v(i),1,rep(i));
end

ومع ذلك ما زلت أشعر أنه يجب أن تكون هناك طريقة أكثر ذكاءً للقيام بذلك ... شكرًا

هل كانت مفيدة؟

المحلول

هذه طريقة واحدة أحب أن أنجز هذا:

>> index = zeros(1,sum(rep));
>> index(cumsum([1 rep(1:end-1)])) = 1;

index =

     1     0     1     0     0     1     1     0     0     0     0

>> index = cumsum(index)

index =

     1     1     2     2     2     3     4     4     4     4     4

>> vv = v(index)

vv =

     3     3     1     1     1     9     4     4     4     4     4

يعمل هذا من خلال إنشاء ناقل فهرس من الأصفار بنفس طول العدد النهائي لجميع القيم. من خلال أداء مجموع تراكمي من rep ناقل مع العنصر الأخير تمت إزالته ووضع 1 في البداية ، أحصل على متجه من المؤشرات في index إظهار أين ستبدأ مجموعات القيم المتكررة. هذه النقاط تتميز بتلك. عندما يتم تنفيذ مبلغ تراكمي index, ، أحصل على ناقل فهرس نهائي يمكنني استخدامه للفهرس فيه v لإنشاء متجه القيم غير المتجانسة.

نصائح أخرى

للإضافة إلى قائمة الحلول الممكنة ، فكر في هذا:

vv = cellfun(@(a,b)repmat(a,1,b), num2cell(v), num2cell(rep), 'UniformOutput',0);
vv = [vv{:}];

هذا أبطأ بكثير من واحد جنوفيس..

ما تحاول القيام به هو فك شفرة طول الجري. فائدة عالية الموثوقة/المتجهة هي التقديم FEX rude():

% example inputs
counts = [2, 3, 1];
values = [24,3,30];

النتائج

rude(counts, values)
ans =
    24    24     3     3     3    30

لاحظ أن هذه الوظيفة تؤدي العملية المعاكسة أيضًا ، أي الترميز الطول عودة ناقل أو بعبارة أخرى values والمقابل counts.

accumarray يمكن استخدام الوظيفة لجعل الكود يعمل في حالة خروج الأصفار rep مجموعة مصفوفة

function vv = repeatElements(v, rep)
index = accumarray(cumsum(rep)'+1, 1);
vv = v(cumsum(index(1:end-1))+1);
end

يعمل هذا على غرار حل Gnovice ، باستثناء أن المؤشرات تتراكم بدلاً من ذلك يتم تعيينها إلى 1. يسمح هذا بتخطي بعض المؤشرات (3 و 6 في المثال أدناه) وإزالة العناصر المقابلة من الإخراج.

>> v = [3 1 42 9 4 42];
>> rep = [2 3 0 1 5 0];
>> index = accumarray(cumsum(rep)'+1, 1)'

index =

     0     0     1     0     0     2     1     0     0     0     0     2

>> cumsum(index(1:end-1))+1

ans =

     1     1     2     2     2     4     5     5     5     5     5

>> vv = v(cumsum(index(1:end-1))+1)

vv =

     3     3     1     1     1     9     4     4     4     4     4
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top