1

I would like to sort an alphanumeric array in Ruby and return a sorted array back.

For example:

["world", "jim", 4, 1, "apple"]

to return:

["apple", "jim", 1, 4, "world"] 

so that where there is an object of the same class in the same position before the sort, just now it's numerical/alphabetical.

4
  • 5
    It seems to me that performing this kind of sort is not the problem here. Needing one is. I don't know your specific use case but you're trying to treat a single array as two separate collections and it smells pretty bad IMHO. Commented Dec 26, 2013 at 23:55
  • 5
    I don't care why the asker wants to do this. It's an interesting question. Commented Dec 27, 2013 at 0:08
  • 3
    @CarySwoveland that's why I'm not downvoting or flagging it. I'm just trying to help the OP by providing my view. It's cool to solve tricky problems in clever ways but I believe that storing objects in arrays should not be tricky in the first place. Commented Dec 27, 2013 at 0:15
  • @Tom, I can't disagree, and have resolved to be less self-indulgent in 2014. Commented Dec 27, 2013 at 5:40

5 Answers 5

1
xs            = ["world", "jim", 4, 1, "apple", 5, 6]
sorted_by_cls = xs.group_by(&:class).each { |k,vs| vs.sort!.reverse! }
sorted_xs     = xs.map(&:class).map { |c| sorted_by_cls[c].pop }
Sign up to request clarification or add additional context in comments.

3 Comments

I'm not sure this is a universal solution to the problem if it's possible for the initial array to contain more groups of Fixnum than just one. For ["world", "jim", 4, 1, "apple", 5, 6] it yields ["apple", "jim", 6, 5, "world", 1, 4]
@Tom Fixed -- forgot the bangs on sort and reverse.
@user3138038 It's group_by, not grouped_by.
1

Don't know how this compares to other solutions, but here's another one:

xs = ["world", "jim", 4, 1, "apple", 5, 6]
classes = xs.map(&:class)
sorts = Hash[*classes.uniq.map {|c| [c, xs.select {|x| x.class == c}.sort]}.flatten(1)]
classes.map {|c| sorts[c].shift} # => ["apple", "jim", 1, 4, "world", 5, 6]

1 Comment

Very nice, Peter. (Forgot to +1 earlier.)
0

A very interesting problem. Here's how I approached it assuming an alphanumeric array. Partition the array into alpha and numeric subarrays, sort them, and reconstitute based on the position and class of the object in the original array.

arr = ["world", "jim", 4, 1, "apple"]
alpha_num = arr.partition { |l| l.is_a? String }.map(&:sort)
arr.map { |l| l.is_a?(String) ? alpha_num.first.shift : alpha_num.last.shift }

My generalized solution is not much different than that of FMc:

arr = ["world", "jim", 4, 1, "apple", 5, 6]
sorted_hash = arr.group_by(&:class).each_value(&:sort!)
arr.map { |l| sorted_hash[l.class].shift }

1 Comment

Very nice. Consider generalizing to arbitrary classes.
0
arr = ["world", "jim", 4, 1, "apple"]

arr.each_with_index.group_by {|e| e.first.class}.values.map {|g|\
g.map(&:first).sort.zip(g.map(&:last).sort)}\
.each_with_object(Array.new(arr.size)) {|e,a| e.each {|f,i| a[i] = f}}
  # => ["apple", "jim", 1, 4, "world"]

Let's go through this:

  • a1 = arr.each.with_index.group_by {|e| e.first.class} # => {String=>[["world", 0], ["jim", 1], ["apple", 4]], Fixnum=>[[4, 2], [1, 3]]}
  • a21, a22 = a1.values #=>[[["world",0],["jim",1],["apple",4]],[[4,2],[1,3]]]
  • a31 = a21.map(&:first) # => ["world", "jim", "apple"]
  • a41 = a31.sort # => ["apple", "jim", "world"]
  • a51 = a21.map(&:last).sort # => [0, 1, 4]
  • a61 = a41.zip(a51) # => [["apple", 0], ["jim", 1], ["world", 4]]
  • a62 = a22.map(&:first).sort.zip(a22.map(&:last).sort) # => [[1,2], [4,3]]
  • [a61, a62].each_with_object(Array.new(5)) {|e,a| e.each {|f,i| a[i] = f}}

Comments

0
a = ["world", "jim", 4, 1, "apple", "cabbage"]

is = a.each_index.group_by{|i| a[i].class}.values
.flat_map{|is| [is, is.sort_by{|i| a[i]}].transpose}
.sort.map(&:last)
a.values_at(*is)

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.