سؤال

وأود أن توسيع مجموعة روبي (التي قد تحتوي على بعض المصفوفات الفرعية) في مجموعة أخرى من المصفوفات تماما كما هو الحال في هذه الأمثلة:

مثال 1: [:foo, :bar]

[
  [:foo, :bar]
]

المثال 2: [:foo, :bar, [:ki, :ku]]

[
  [:foo, :bar, :ki],
  [:foo, :bar, :ku]
]

المثال 3: [:foo, :bar, :baz, [:a, :i, :u, :e, :o], :qux]

[
  [:foo, :bar, :baz, :a, :qux],
  [:foo, :bar, :baz, :i, :qux],
  [:foo, :bar, :baz, :u, :qux],
  [:foo, :bar, :baz, :e, :qux],
  [:foo, :bar, :baz, :o, :qux]
]

المثال 4: [:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]

[
  [:foo, :bar, :baz, :a, 1, :qux],
  [:foo, :bar, :baz, :i, 1, :qux],
  [:foo, :bar, :baz, :u, 1, :qux],
  [:foo, :bar, :baz, :e, 1, :qux],
  [:foo, :bar, :baz, :o, 1, :qux],
  [:foo, :bar, :baz, :a, 2, :qux],
  [:foo, :bar, :baz, :i, 2, :qux],
  [:foo, :bar, :baz, :u, 2, :qux],
  [:foo, :bar, :baz, :e, 2, :qux],
  [:foo, :bar, :baz, :o, 2, :qux]
]

المثال 5: [:foo, [[], :c], :bar]

[
  [:foo, [], :bar],
  [:foo, :c, :bar]
]

المثال 6: [:foo, [[:a, :b], :c], :bar]

[
  [:foo, [:a, :b], :bar],
  [:foo, :c, :bar]
]

ملاحظة:يجب توسيع المصفوفات الفرعية فقط.لهذا السبب ، في المثال 5 و 6 ، لا يتم توسيع المصفوفات الفرعية الفرعية.

شكرا جزيلا على أي اقتراحات أو قطعة من التعليمات البرمجية.

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

المحلول

لقد استخدمت product فكرة للوصول إلى هذه الوظيفة:

def trans(a)
  b = a.map{|e| [e].flatten(1)}
  b.first.product(*b.slice(1..-1))
end

على سبيل المثال ، هذا الرمز:

puts trans([:foo, :bar]).inspect
puts trans([:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]).inspect
puts trans([:foo, [[], :c], :bar]).inspect
puts trans([:foo, [[:a, :b], :c], :bar]).inspect

يعطي هذا:

[[:foo, :bar]]
[[:foo, :bar, :baz, :a, 1, :qux],
 [:foo, :bar, :baz, :a, 2, :qux],
 [:foo, :bar, :baz, :i, 1, :qux],
 [:foo, :bar, :baz, :i, 2, :qux],
 [:foo, :bar, :baz, :u, 1, :qux],
 [:foo, :bar, :baz, :u, 2, :qux],
 [:foo, :bar, :baz, :e, 1, :qux],
 [:foo, :bar, :baz, :e, 2, :qux],
 [:foo, :bar, :baz, :o, 1, :qux],
 [:foo, :bar, :baz, :o, 2, :qux]]
[[:foo, [], :bar],
 [:foo, :c, :bar]]
[[:foo, [:a, :b], :bar],
 [:foo, :c, :bar]]

تحرير: شرح للرمز أعلاه.

ال لمحة عامة الفكرة هي أننا نريد منتجا لجميع العناصر في المصفوفة.إذا نظرت إلى وثائق مجموعة # المنتج, ، سترى أنه يفعل ما تريد we علينا فقط أن نسميها بشكل مناسب.

أولا, product يعمل على المصفوفات ، لذلك علينا التأكد من أن جميع العناصر في صفيفتنا الأصلية هي صفيف نفسها.هذه هي مهمة السطر الأول من الوظيفة:

b = a.map{|e| [e].flatten(1)}

نقوم بتحويل جميع العناصر في المصفوفة باستخدام map.التحويل يجعل صفيف مع العنصر e في الداخل ، ثم يسطح هذا الصفيف الجديد.إما أن العنصر الأصلي كان مصفوفة أو لم يكن كذلك;إذا لم يكن صفيف, [e].flatten(1) لن تفعل شيئا وسوف يعود [e];إذا كان صفيف, [e] سوف تقييم ل [[x]], ، والتي سيتم تسويتها بعد ذلك إلى [x].ال 1 يقول flatten للذهاب فقط 1 مستوى عميق.

ثم كل ما علينا فعله هو الاتصال product على العنصر الأول يمر كوسائط العناصر المتبقية من المصفوفة المعدلة:

b.first.product(*b.slice(1..-1))

هنا, b.slice(1..-1) يعني:تأخذ عناصر من ب ، بدءا من 2 على طول الطريق إلى الماضي.أخيرا ، تشير العلامة النجمية إلى أننا لا نريد تمرير المصفوفة كوسيطة ، ولكن بدلا من ذلك عناصر المصفوفة.

نصائح أخرى

يبدو أنك ترغب في الحصول على منتج ديكارتي لعناصر المصفوفة المعنية.يجب أن يعمل هذا الرمز من أجلك:

array = [:foo, :bar, :baz, [:a, :i, :u, :e, :o], [1, 2], :qux]
array.inject([[]]) do |product,element|
  result = []
  if element.is_a?(Array)
    product.each do |tuple|
      element.each do |last|
        result << tuple + [last]
      end
    end
  else
    product.each do |tuple|
      result << tuple + [element]
    end
  end
  result
end

يمكنك تبسيطها قليلا عن طريق تحريك الشرطي إلى الحلقة ، لكن هذا سيجعلها أقل كفاءة.

وبالنظر إلى أنك تستخدم أمثلة بدلا من شيء صريح أود أن أقترح وجود الجر من خلال وثائق طريقة الصفيف.بالنسبة للمبتدئين إلقاء نظرة على الطرق التالية:

.combination.to_a
.shift
.transpose
.flatten
.zip
.take

تعتمد كيفية التنفيذ على ما إذا كنت تعرف ما تقوم بتحويله في كل حالة أم أنك تحاول بناء شيء عام (أي.تمديد فئة الصفيف.لكل فما استقاموا لكم فاستقيموا التعامل مع مجموعة المدخلات في مجموعة الهدف.المثال 1 سهل:

input = [:foo,:bar]
target = Array.new
target << input        => [[:foo,:bar]]

بالنسبة لبقية الأمثلة هناك طرق متعددة للوصول إلى هناك اعتمادا على ما تحاول القيام به ، وكيف تريد روبي لمعرفة ما يجب القيام به عندما قدمت مع المدخلات.في المثال 2 الأول هو الكتابة مباشرة:

input = [:foo, :bar, [:ki, :ku]]
target = Array.new

target << [input[0], input[1], input[2][0]]
target << [input[0], input[1], input[2][1]]

أو اللعب بأساليب الصفيف:

target = input.pop
target = [input, input].zip(target).flatten
target = [target[0..(target.size/2)-1], target[target.size/2..-1]]

أو إذا لم تكن تعرف أي جزء من المصفوفة يحتوي على مصفوفة فرعية ، فيمكنك اكتشافه:

input.each do |i|
  if i.class == Array
    holding = i
  end
end

انها حقا يتوقف على كل كيف تريد تحديد والتعامل مع مجموعة!

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