Arrays 扩展数组以检查它是否在Swift中排序?

Arrays 扩展数组以检查它是否在Swift中排序?,arrays,swift,Arrays,Swift,我想扩展数组类,这样它就可以知道它是否被排序(升序)。我想添加一个名为isSorted的计算属性。如何声明数组的元素具有可比性 我目前在操场上的实施 extension Array { var isSorted: Bool { for i in 1..self.count { if self[i-1] > self[i] { return false } } return true } } // The way I want to get th

我想扩展数组类,这样它就可以知道它是否被排序(升序)。我想添加一个名为
isSorted
的计算属性。如何声明数组的元素具有可比性

我目前在操场上的实施

extension Array {
  var isSorted: Bool {
    for i in 1..self.count {
      if self[i-1] > self[i] { return false }
    }
    return true
  }
}

// The way I want to get the computed property
[1, 1, 2, 3, 4, 5, 6, 7, 8].isSorted //= true
[2, 1, 3, 8, 5, 6, 7, 4, 8].isSorted //= false
错误
找不到接受提供的参数的'>'的重载


当然,我仍然有一个错误,因为斯威夫特不知道如何比较元素。如何在Swift中实现此扩展?还是我做错了什么?

您遇到了Swift泛型的问题,现在无法以您喜欢的方式解决(可能在未来的Swift版本中)。另见

目前,您需要定义一个函数(例如在全局范围内):

func排序(数组:数组)->Bool{
对于1..array[i]中的i{
返回错误
}
}
返回真值
}
设i=[1,2,3]
设j=[2,1,3]
设k=[UIView(),UIView()]
println(isSorted(i))//打印“true”
println(isSorted(j))//打印“false”
println(isSorted(k))//错误:调用中缺少参数#2的参数

IMHO,错误消息具有误导性,因为实际错误类似于“UIView不满足可比的类型约束”。

自由函数的替代解决方案是执行Swift内置的
Array.sort
Array.sorted
方法所做的操作,并要求将合适的比较器传递给该方法:

extension Array {
    func isSorted(isOrderedBefore: (T, T) -> Bool) -> Bool {
        for i in 1..<self.count {
            if !isOrderedBefore(self[i-1], self[i]) {
                return false
            }
        }
        return true
    }
}

[1, 5, 3].isSorted(<) // false
[1, 5, 10].isSorted(<) // true
[3.5, 2.1, -5.4].isSorted(>) // true
扩展数组{
函数排序(在:(T,T)->Bool)->Bool之前排序){

对于Swift 2.0中的i..,您现在可以扩展协议了

extension CollectionType where Generator.Element: Comparable {

    public var isSorted: Bool {

        var previousIndex = startIndex
        var currentIndex = startIndex.successor()

        while currentIndex != endIndex {

            if self[previousIndex] > self[currentIndex] {
                return false
            }

            previousIndex = currentIndex
            currentIndex = currentIndex.successor()
        }

        return true
    }

}

[1, 2, 3, 4].isSorted // true
["a", "b", "c", "e"].isSorted // true
["b", "a", "c", "e"].isSorted // false
[/* Anything not implementing `Comparable` */].isSorted // <~~ Type-error
Generator.Element所在的扩展集合类型:可比较{
公共变量分类:Bool{
var previousIndex=startIndex
var currentIndex=startIndex.successiver()
而currentIndex!=endIndex{
如果self[previousIndex]>self[currentIndex]{
返回错误
}
previousIndex=currentIndex
currentIndex=currentIndex.successiver()
}
返回真值
}
}
[1,2,3,4]。isSorted//true
[“a”、“b”、“c”、“e”]。isSorted//true
[“b”、“a”、“c”、“e”]。isSorted//false

[/*任何不实现“可比”*/].isSorted/对我来说,最灵活的解决方案是结合NSAddict和Wes Campave的答案。即,结合了能够扩展协议和将比较器函数作为参数传递的优势。这消除了仅将其用于数组和将其约束到符合
Compariable协议

extension CollectionType
{
    func isSorted(isOrderedBefore: (Generator.Element, Generator.Element) -> Bool) -> Bool
    {
        var previousIndex = startIndex
        var currentIndex = startIndex.successor()

        while currentIndex != endIndex
        {
            if isOrderedBefore(self[previousIndex], self[currentIndex]) == false
            {
                return false
            }

            previousIndex = currentIndex
            currentIndex = currentIndex.successor()
        }

        return true
    }
}
这可以用于任何
集合
类型,并且可以根据您的需要定义排序标准。

适应,这将在Swift 4中起作用

扩展数组,其中Iterator.Element:可比较{ func被排序(isOrderedBefore:(Iterator.Element,Iterator.Element)->Bool)->Bool{ 对于1中的i..
实际上,您可以扩展
序列
协议以获得更通用的解决方案:

扩展序列{
函数被排序(按递增顺序:(元素,元素)抛出->布尔)再抛出->布尔{
var iterator=makeIterator()
guard var previous=iterator.next()else{
//序列为空
返回真值
}
而让current=iterator.next(){
guard try areInIncreasingOrder(上一个,当前)else{
返回错误
}
先前=当前
}
返回真值
}
}
扩展序列,其中元素:可比较{
func isSorted()->Bool{

return isSorted(按:这里是Swift 4中的一个解决方案,当
self.count
等于或小于1时不会崩溃:

extension Array where Element: Comparable {
    func isSorted(by isOrderedBefore: (Element, Element) -> Bool) -> Bool {
        for i in stride(from: 1, to: self.count, by: 1) {
            if !isOrderedBefore(self[i-1], self[i]) {
                return false
            }
        }
        return true
    }
}
此代码段假定已对包含1或0个元素的数组进行排序

在for循环范围中以1开头的原因是:如果self.count=)//true [1,4,7].isSorted(由:{x,y in.) 返回x+2
如果您想要不带参数的简单函数,如Swift中的sort()或sorted():

extension Array where Element : Comparable {
    func isSorted() -> Bool {
        guard self.count > 1 else {
            return true
        }

        for i in 1..<self.count {
            if self[i-1] > self[i] {
                return false
            }
        }
        return true
    }
}
扩展数组,其中元素:可比较{
func isSorted()->Bool{
防护自我计数>1其他{
返回真值
}
因为我在1..self[i]{
返回错误
}
}
返回真值
}
}
通用功能,可以为实现提供快捷方式

extension Collection where Element: Comparable {
    var isSorted: Bool {
        guard count > 1 else {
            return true 
        }

        let pairs = zip(prefix(count - 1), suffix(count - 1))

        return !pairs.contains { previous, next in
            previous > next
        }
    }
}

[0, 1, 1, 2].isSorted  // true
[0, 2, 2, 1].isSorted  // false

在Swift 4.2及更高版本中,您可以通过一些序列切片来拼凑:

扩展数组,其中元素:可比较{
func isascing()->Bool{
返回zip(self,self.dropFirst()).allsuccess(Bool{
返回zip(self,self.dropFirst()).allsuccess(>=)
}
}

@kAzec的答案似乎在元素相等时不起作用。这是因为根据定义,递增顺序(a,a)必须为false

以下方法应该可以很好地工作

扩展序列{
func被排序(按areInIncreasingOrder:(元素,元素)抛出->布尔)
后退->布尔{
var it=makeIterator()
guard var previous=it.next()else{return true}
而让current=it.next(){
如果尝试!正在递增顺序(上一个,当前)&&
areInIncreasingOrder(当前、以前){
返回错误
}
先前=当前
}
返回真值
}
}
扩展序列,其中元素:可比较{
func isSorted()->Bool{

返回排序(通过:总结前面的答案有一个最小的通用数组扩展要检查:

扩展数组{
func被排序(u谓词:(元素,元素)抛出->Bool)
[1, 2, 3].isSorted(by: >) // true
[3, 2, 2].isSorted(by: >=) // true
[1, 4, 7].isSorted(by: {x, y in
    return x + 2 < y * y
}) // true

let a: [Int] = [1]
a.isSorted(by: <) // true


let b: [Int] = []
b.isSorted(by: >) // true
extension Array where Element : Comparable {
    func isSorted() -> Bool {
        guard self.count > 1 else {
            return true
        }

        for i in 1..<self.count {
            if self[i-1] > self[i] {
                return false
            }
        }
        return true
    }
}
extension Collection where Element: Comparable {
    var isSorted: Bool {
        guard count > 1 else {
            return true 
        }

        let pairs = zip(prefix(count - 1), suffix(count - 1))

        return !pairs.contains { previous, next in
            previous > next
        }
    }
}

[0, 1, 1, 2].isSorted  // true
[0, 2, 2, 1].isSorted  // false