0

I'm trying to take an array like

[ "First.Package", "Second.Package" ]

and turn it into

[ "First.Package.ads", "First.Package.adb", "Second.Package.ads", "Second.Package.adb" ]

I've tried doing the following:

packages = [ "First.Package", "Second.Package" ]
files = []
packages.each do |package|
    files << (package << ".ads")
    files << (package << ".adb")
end
return files

Which does not do what I think it should do. I get:

First.Package.ads.adb
First.Package.ads.adb
Second.Package.ads.adb
Second.Package.ads.adb

I want:

First.Package.ads
First.Package.adb
Second.Package.ads
Second.Package.adb
1
  • 1
    A different approach arr.flat_map { |str| [str+".ads",str+".adb"] } Commented May 31, 2017 at 20:34

3 Answers 3

5
packages = ["First.Package", "Second.Package"]
suffixes = [".ads", ".adb"]

packages.product(suffixes).map(&:join)
  #=> ["First.Package.ads", "First.Package.adb",
  #    "Second.Package.ads", "Second.Package.adb"]

Note that

packages.product(suffixes)
  #=> [["First.Package", ".ads"], ["First.Package", ".adb"],
  #    ["Second.Package", ".ads"], ["Second.Package", ".adb"]]

See Array#product.

Sign up to request clarification or add additional context in comments.

2 Comments

This is cool and you get my upvote, but using cartesian product on filenames may just be a little too clever for some teams...
I'd go with this. It will work if packages or suffixes get new elements without having to write more code.
4

package << ".ads mutates state of package. Use + for string concatenation in places like that, because it doesn't mutate state. It just returns new string(which is what you really want).

packages.each do |package|
    files << (package + ".ads")
    files << (package + ".adb")
end

this should work for your case

3 Comments

...and to eliminate files = [] and return files, write packages.each_with_object(files) do |package, files| followed by what you have.
You can also use push here which takes multiple arguments, like files.push(package + ".ads", package + ".adb"). Whether it's better to do so I'm not sure.
The problem is that additional code has to be written if an additional extension is added. Instead, the code should not care.
3

Given

packages = %w(First.Package Second.Package)
extensions = %w(.ads .adb)

You could do it like this:

files = packages.map do |package|
  extensions.map do |extension|
    package + extension
  end
end.flatten

1 Comment

Consider using flat_map instead of the outer map. This will save you having to flatten at the end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.