0

I have an array:

["apple", "banana", "animal", "car", "angel"]

I want to push elements that start with "a" into separate arrays. I want to return:

["apple"], ["animal"], ["angel"]

I have only been able to make it work if I push them into an empty array that I pre-created.

5
  • 1
    I think your actual question is the following: given an array of strings arr, return an array comprised of the those elements of arr that begin with "a", in the same order. The way it is now worded it sounds like you wish to create a new empty array, say b, and then iterate over arr, executing b.push(string) (or b << string) when the element string of arr begins with an "a". Do you see how that unnecessarily restricts the method of solution? @djaszczurowski's answer, for example, does not seem to meet your requirements but, imo, is the best answer. Commented Mar 22, 2018 at 17:55
  • As you are fairly new to SO you may not realize there is no urgency to select what you consider to be the most helpful answer. If you wait awhile--say a couple of hours or more--you generally have more answers to choose from. Also, an early selection can discourage the posting of other answers and (imo) is inconsiderate to those still working on their answers. Note that you can always change your selection if a better answer is posted after you have made your selection. Commented Mar 22, 2018 at 18:03
  • Ruby methods return objects. ["apple"], ["animal"], ["angel"] is not an object. I assume you mean you wish to return an array. Do you want [["apple"], ["animal"], ["angel"]] or ["apple", "animal", "angel"]? Some answers assume the former is wanted. Commented Mar 22, 2018 at 18:24
  • Please edit your question to make it clear. The array you speak of is unfinished and not formatted properly. Commented Mar 22, 2018 at 19:01
  • What is your question? Commented Mar 23, 2018 at 3:30

5 Answers 5

4

Generally in order to pick elements from array that match some specific conditione use select method.

select returns an array of all elements that matched critera or an empty list in case neither element has matched

example:

new_array = array.select do |element|
  return_true_or_false_depending_on_element(element)
end

now when we would like to put every element in its own array we could you another array method that is available on array - map which takes every element of an array and transforms it in another element. In our case we will want to take every matching string and wrap it in array

map usage:

new_array = array.map do |element|
  element_transformation(element) # in order to wrap element just return new array with element like this: [element]
end

coming back to your question. in order to verify whether a string starts with a letter you could use start_with? method which is available for every string

glueing it all together:

strings = ["apple", "banana", "animal", "car", "angel"]

result = strings.select do |string|
  string.start_with?("a")
end.map do |string_that_start_with_a|
  [string_that_start_with_a]
end

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

5 Comments

+1, best option IMO. I would add that reject is the exact opposite of select: reject Returns a new array containing the items in self for which the block is not true (apidock.com/ruby/Array/reject)
select is clearly the way to go, but I would prefer to see your answer shortened and tighteneed. Were it me, I would just define strings as you have and write strings.select { |string| string.start_with?(a) } #=> ["apple", "animal", "angel"], then explain that Array#select returns an array consisting of all elements string of strings for which string.start_with?("a") evaluates true.
it was deliberately done this way - we (as people) tend to just copy paste what seems to solve our problem, often without considering what happens. That's why I started with generic approach, eventually providing solution for author's question. He strongly suggested that he is a beginner to ruby so I believe this makes more sense. Thanks for feedback!
This should be the accepted answer! BTW, any opinion on string.start_with?("a") vs string[0] == "a"? Just curious.
thanks. answering your question - actually for given case is no difference, but in general start_with? seems to be more ruby idiomatic approach. Things get more complicated in case you would have an empty string inside an array - string[0] would return nil, so essentially you would be comparing nil against "a" which will work as we think it should work, but it's a bit tricky. it's even more fun when you test if empty string starts with an empty string (test yourself ""[0] == "" and "".start_with?(""))
1

Here's a golfed down version:

array.grep(/\Aa/).map(&method(:Array))

I might consider my audience before putting something this clever into production, since it can be a little confusing.

Array#grep returns all elements that match the passed regular expression, in this case /\Aa/ matches strings that begin with a. \A is a regular expression token that matches the beginning of the string. You could change it to /\Aa/i if you want it to be case insensitive.

The &method(:Array) bit grabs a reference to the kernel method Array() and runs it on each element of the array, wrapping each element in the array in its own array.

2 Comments

As you're golfing, .map{|s|[s]} saves 9 characters. grep is good.
Ah, yeah. I should've said "snappy one liner" instead of "golfed down". I think yours might be more readable than mine if we expand the naming: array.grep(/\Aa/).map { |word| [word] }.
0

The simplest I can come up with is:

arr = %w{ apple banana animal car angel }

arr.map {|i| i.start_with?('a') ? [i] : nil }.compact

=> [["apple"], ["animal"], ["angel"]]

7 Comments

.flatten on the end will make this a 1d array
How would I extract this to work on any array given by the user?
def find_words_with_a(arr) return arr.map {|i| i.start_with?('a') ? [i] : nil }.compact.flatten end
The ternary operator seems superfluous. If something doesn't start with "a" map will eventually use nil for that value.
@SebastianPalma Right, but you still have to express the conditionality since start_with? does not return the value but a boolean result. Otherwise you would not need the operator.
|
0

Here is some code I got to do this in console:

> arr = ["apple", "banana", "animal", "car", "angel"]
=> ["apple", "banana", "animal", "car", "angel"] 
> a_words = []
=> [] 
arr.each do |word|
  a_words << word if word.chars.first == 'a'
end
=> ["apple", "banana", "animal", "car", "angel"]
> a_words
=> ["apple", "animal", "angel"]

If you wanted to do something more complex than first letter you might want to use a regex like:

if word.matches(/\Aa/)  # \A is beginning of string

1 Comment

You can simply write word[0] instead of word.chars.first.
0
array_of_arrays = []
your_array.each do |ele|
  if ele.starts_with?("a")
    array_of_arrays << ele.to_a
  end
end

Comments

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.