How can you sort an array in Ruby starting with a specific letter, for example, the letter f?

I have a text array.

text_array = ["bob", "alice", "dave", "carol", "frank", "eve", "jordan", "isaac", "harry", "george"]

text_array = text_array.sort will give us a sorted array.

However, I need a sorted array with f as the first letter for our order, and e as the last.

So, the end result should be ...

text_array = ["frank", "george", "harry", "isaac", "jordan", "alice", "bob", "carol", "dave", "eve"]

What would be the best way to achieve this?

+4
source share
5 answers

I think the easiest way would be to rotate the sorted array:

text_array.rotate(offset) if offset = text_array.find_index { |e| e.size > 0 and e[0] == 'f' }
+3
source

Try the following:

result = (text_array.select{ |v| v =~ /^[f-z]/ }.sort + text_array.select{ |v| v =~ /^[a-e]/ }.sort).flatten

This is not the most beautiful, but he will do his job.

Change for comment. Creating a more general piece of code:

before = []
after = []
text_array.sort.each do |t|
  if t > term
    after << t
  else
    before << t
  end
end
return (after + before).flatten

, term - , . term, .

+4

:

alpha = ('a'..'z').to_a
  #=> ["a", "b", "c",..."x", "y", "z"] 
reordered = alpha.rotate(5) 
  #=> ["f", "g",..."z", "a",...,"e"] 
h = reordered.zip(alpha).to_h
  # => {"f"=>"a", "g"=>"b",..., "z"=>"u", "a"=>"v",..., e"=>"z"}

text_array.sort_by { |w| w.gsub(/./,h) }
  #=> ["frank", "george", "harry", "isaac", "jordan",
  #   "alice", "bob", "carol", "dave", "eve"] 

:

a_to_z = alpha.join
  #=> "abcdefghijklmnopqrstuvwxyz" 
f_to_e = reordered.join
  #=> "fghijklmnopqrstuvwxyzabcde"

text_array.sort_by { |w| w.tr(f_to_e, a_to_z) }
  #=> ["frank", "george", "harry", "isaac", "jordan",
  #   "alice", "bob", "carol", "dave", "eve"] 
+3

Ryan K , , - :

text_array = text_array.sort!.select {|x| x.first >= "f"} + text_array.select {|x| x.first < "f"}
+1

, , .

. , , .

, , -

an_array = ["bob", "alice", "dave", "carol", "frank", "eve", "jordan", "isaac", "harry", "george"]

# Define your patterns with scores so that the sorting result can vary  accordingly
# It full fledged Regex so you can put any kind of regex you want.
patterns = {
  /^f/ => 100,
  /^e/ => -100,
  /^g/ => 60,
  /^j/ => 40
}

# Sort the array with our preferred sequence
sorted_array = an_array.sort do |left, right|
  # Find score for the left string
  left_score = patterns.find{ |p, s| left.match(p) }
  left_score = left_score ? left_score.last : 0

  # Find the score for the right string
  right_score = patterns.find{ |p, s| right.match(p) }
  right_score = right_score ? right_score.last : 0

  # Create the comparision score to prepare the right order
  # 1 means replace with right and -1 means replace with left
  # and 0 means remain unchanged
  score = if right_score > left_score
    1
  elsif left_score > right_score
    -1
  else
    0
  end

  # For debugging purpose, I added few verbose data
  puts "L#{left_score}, R:#{right_score}: #{left}, #{right} => #{score}"

  score
end

# Original array
puts an_array.join(', ')

# Biased array
puts sorted_array.join(', ')
0

All Articles