Check to see if an array is already sorted?

匿名 (未验证) 提交于 2019-12-03 01:39:01

问题:

I know how to put an array in order, but in this case I just want to see if it is in order. An array of strings would be the easiest, I imagine, and answers on that front are appreciated, but an answer that includes the ability to check for order based on some arbitrary parameter is optimal.

Here's an example dataset. The name of:

[["a", 3],["b",53],["c",2]]

Where the elements are themselves arrays containing several elements, the first of which is a string. I want to see if the elements are in alphabetical order based on this string.

回答1:

It's a generic abstraction, let's open Enumerable:

module Enumerable   def sorted?     each_cons(2).all? { |a, b| (a <=> b) <= 0 }   end end  [["a", 3], ["b", 53],["c", 2]].sorted? #=> true

Notice that we have to write (a <=> b) <= 0 instead of a <= b because there are classes that support <=> but not the comparator operators (i.e. Array), since they do not include the module Comparable.

You also said you'd like to have the ability "to check for order based on some arbitrary parameter":

module Enumerable     def sorted_by?     each_cons(2).all? { |a, b| ((yield a) <=> (yield b)) <= 0 }       end end  [["a", 3], ["b", 1], ["c", 2]].sorted_by? { |k, v| v } #=> false

With lazy enumerables (Ruby >= 2.1) it's much nicer, we can reuse Enumerable#sorted?:

module Enumerable     def sorted_by?(&block)     lazy.map(&block).sorted?   end end


回答2:

You can compare them two by two:

[["a", 3],["b",53],["c",2]].each_cons(2).all?{|p, n| (p <=> n) != 1} # => true


回答3:

reduce can compare each element to the one before, and stop when it finds one out of order:

array.reduce{|prev,l| break unless l[0] >= prev[0]; l}


回答4:

If it turns out the array isn't sorted, will your next action always be to sort it? For that use case (though of course depending on the number of times the array will already be sorted), you may not want to check whether it is sorted, but instead simply choose to always sort the array. Sorting an already sorted array is pretty efficient with many algorithms and merely checking whether an array is already sorted is not much less work, making checking + sorting more work than simply always sorting.



回答5:

def ascending? (array)     yes = true     array.reduce { |l, r| break unless yes &= (l[0] <= r[0]); l }     yes end   def descending? (array)     yes = true     array.reduce { |l, r| break unless yes &= (l[0] >= r[0]); l }     yes end


回答6:

Iterate over the objects and make sure each following element is >= the current element (or previous is <=, obviously) the current element.



回答7:

For this to work efficiently you will want to sort during insertion. If you are dealing with unique items, a SortedSet is also an option.

For clarification, if we patch array to allow for a sorted insertion, then we can keep the array in a sorted state:

class Array   def add_sorted(o)     size = self.size     if size == 0       self << o     elsif self.last < o       
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!