Reputation: 459
I am trying to solve this problem: given a string, you are asked to sort it according to characters order in other string:
Example:
> sort_string('foos', 'of')
=> 'oofs'
> sort_string('string', 'gnirts')
=> 'gnirts'
> sort_string('banana', 'abn')
=> 'aaabnn'
I've tried following implementation:
def sort_string(f_string, s_string)
sanitize(s_string)
s_string.chars.each do |e|
f_string.length.times do |n|
if f_string[n] == e
s_string[e], s_string[n] = s_string[n], s_string[e]
end
end
end
end
private
def sanitize(string)
string.chars.uniq.join
end
But it gives me following error:
4_AStringOfSorts.rb:6:in `[]=': no implicit conversion of nil into String (TypeError) from 4_AStringOfSorts.rb:6:in `block (2 levels) in sort_string' from 4_AStringOfSorts.rb:4:in `times' from 4_AStringOfSorts.rb:4:in `block in sort_string' from 4_AStringOfSorts.rb:3:in `each' from 4_AStringOfSorts.rb:3:in `sort_string' from 4_AStringOfSorts.rb:18:in `'
Upvotes: 2
Views: 141
Reputation: 110685
If @tokland's interpretation of the question is correct, it can also be done thus, without sorting per se:
def sort_string(s, order)
sa = s.chars
order.each_char.with_object('') do |c,str|
while (idx = sa.index(c))
str << sa.delete_at(idx)
end
end + sa.join
end
sort_string('zaefcf', 'fa')
#=>"ffazec"
Here's another way that uses sort_by
, but only on the part of the string that requires sorting:
def sort_string(s, order)
sa = s.chars
e = sa - order.chars
(sa - e).sort_by { |c| order.index(c) }.concat(e).join
end
sort_string('zaefcf', 'fa')
#=> "ffazec"
Upvotes: 0
Reputation: 116
A similar approach:
def sort_string(s, order)
order.chars.map { |c| c * s.count(c) }.join
end
Upvotes: 2
Reputation: 67870
Notes:
Your approach is not idiomatic in Ruby (it's overly complicated even by imperative standards)
sanitize(s_string)
: you don't capture the result of this method, so it's doing nothing.
A more idiomatic and functional approach:
def sort_string(s, order)
s.chars.sort_by { |c| order.index(c) || order.size }.join
end
Upvotes: 4