4
\$\begingroup\$

This is a method which creates an array of all possible consecutive substrings from a string:

def get_seperated_tokens(query)
 result = []
 length = query.split.count
 tokens = query.downcase.strip.split(' ')
 length.times do |i|
 length.times do |j|
 result << tokens[i..j].join(' ') if j >= i
 end
 end
 result
end

To get a better idea I have added rspec for it:

describe "#get_seperated_tokens" do
 it "returns an array of seperated tokens" do
 query = 'ruby is awesome'
 result = ['ruby','is', 'awesome', 'ruby is', 'is awesome','ruby is awesome']
 expect(get_seperated_tokens(query)).to include(*result)
 end
 it "returns an array of seperated tokens" do
 query = 'red blue iphones'
 result = ['red','blue', 'iphones', 'red blue', 'blue iphones','red blue iphones']
 expect(get_seperated_tokens(query)).to include(*result)
 end
end

How can this be made more idiomatic?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Jul 19, 2013 at 8:21
\$\endgroup\$
1

2 Answers 2

2
\$\begingroup\$

As @Michael Szyndel mentioned in a comment, Array#combination is the more appropriate method to use.

def get_separated_tokens query
 tokens = query.split
 (0..tokens.size).to_a.combination(2).map{ |i,j| tokens[i...j].join " " }
end
200_success
145k22 gold badges190 silver badges478 bronze badges
answered Jul 20, 2013 at 20:19
\$\endgroup\$
3
  • \$\begingroup\$ In fact Michael wrote an answer with combination (now deleted), the problem is that OP needs contiguous combinations, so this won't do. \$\endgroup\$ Commented Jul 21, 2013 at 9:17
  • \$\begingroup\$ @tokland, I don't get you. Did you run this code? It produces the same as OP's code. \$\endgroup\$ Commented Jul 22, 2013 at 10:29
  • \$\begingroup\$ oh, you're right, you use combinations, but with a slice later, which is right. +1 \$\endgroup\$ Commented Jul 22, 2013 at 10:34
1
\$\begingroup\$

Are you familiar with functional programming? (my page on the subject: FP with Ruby). Your code feels clunky because, well, imperative programming is clunky (recommended reading: Can Programming Be Liberated From The Von Neumann Style?).

You just need to re-write the code without times (as it's being used as an each), mutable variables (result = []), inplace operations (<<) and inline conditionals with side-effects (do_something if j >= i). I'd write:

def get_separated_tokens(query)
 tokens = query.split
 (0...tokens.size).flat_map do |istart|
 (istart...tokens.size).map do |iend|
 tokens[istart..iend].join(" ")
 end
 end
end
p get_separated_tokens("ruby is awesome")
#["ruby", "ruby is", "ruby is awesome", "is", "is awesome", "awesome"]
answered Jul 19, 2013 at 11:35
\$\endgroup\$
1
  • \$\begingroup\$ You can select Nakilon's answer, I calculated the combinations to build ranges, we have Array#combination. \$\endgroup\$ Commented Jul 22, 2013 at 10:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.