ترجمة صفيف إلى بعض المصفوفات
-
11-12-2019 - |
سؤال
وأود أن توسيع مجموعة روبي (التي قد تحتوي على بعض المصفوفات الفرعية) في مجموعة أخرى من المصفوفات تماما كما هو الحال في هذه الأمثلة:
مثال 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
انها حقا يتوقف على كل كيف تريد تحديد والتعامل مع مجموعة!