【问题标题】:How to sort an Array of Tuples using sorted? (Cannot invoke 'sorted' with an argument list of type)如何使用 sorted 对元组数组进行排序? (不能使用类型参数列表调用“排序”)
【发布时间】:2016-12-11 16:01:48
【问题描述】:

我正在尝试使用sorted 对元组数组进行排序。

我得到的错误是:

无法使用 (((MyClass1, MyClass2)) -> Bool) 类型的参数列表调用“排序”

数组是这样创建的:

class MyClass1 {
    var id: Int
    init(id:Int) { self.id = id }
}

class MyClass2 {
    var id2: Int
    init(id2:Int) { self.id2 = id2 }
}
let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
var tuples = zip(array1, array2)

我尝试过的:

tuples = tuples.sorted { (left, right) -> Bool in
    return left.1.id2 > right.1.id2
}

tuples = tuples.sorted { $0.1.id2 > $1.1.id2 }

tuples = tuples.sorted(by: { (first: (MyClass1, MyClass2), second: (MyClass1, MyClass2)) -> Bool in
    return first.1.id2 > second.1.id2
})

预期的输出是(伪,手写):

[(myClass1WithId_1, myClass2WithId2_4),(myClass1WithId_2, myClass2WithId2_3),(myClass1WithId_3, myClass2WithId2_2),(myClass1WithId_4, myClass2WithId2_1)]

按 myClass2.id2 降序排序的元组。


更新

我找到了解决此问题的方法。该错误似乎是错误的/具有误导性。

我可以在将结果分配给新变量时对其进行排序:

let tuples2 = tuples.sorted { (left, right) -> Bool in
    return left.1.id2 > right.1.id2
}

将其分配给现有变量时,会出现上述错误:

tuples = tuples.sorted { (left, right) -> Bool in
    return left.1.id2 > right.1.id2
}

【问题讨论】:

  • 这取决于您希望如何对数据进行排序。你能提供一个示例输入和预期输出吗?
  • 更新了预期输出的问题。
  • 很有趣。侦探工作也很好。

标签: arrays swift sorting swift3


【解决方案1】:

我正在尝试对元组数组进行排序

但问题是您的tuples 不是 数组。 (这是一种称为 Zip2Sequence 的东西。)解决方案是将其强制转换为数组:

var tuples = Array(zip(array1, array2))

现在你的原始代码可以工作了:

let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
var tuples = Array(zip(array1, array2)) // *
tuples = tuples.sorted { (left, right) -> Bool in
    return left.1.id2 > right.1.id2
}

您的 解决方案起作用的原因是排序后的序列会产生一个数组。因此,您不能将数组重新分配给序列变量 (tuples),但可以将其分配给不同的变量 (tuples2)。我的解决方案以数组开始,因此生成的排序数组可以分配回同一个变量。

【讨论】:

  • 不错的发现。我必须查看Zip2Sequence 以找出为什么它不返回数组。谢谢!
  • 嗯,接下来要做的通常是for...in,所以你只需要一个序列。而且这个序列是lazy的,所以在你真正做for...in之前没有工作要做。序列不是集合(但集合是序列,而数组是两者)。您无法对序列进行排序。
  • 您当然可以对序列进行排序。
  • @shallowThought zip(_:_:) 不会返回 Array,因为几乎没有理由证明它是正确的。它返回Zip2Sequence,这是一个包装了2个迭代器(你给它的2个序列)的结构,它同步迭代它们。将其转换为数组会更慢,因为必须迭代n 元素,并且浪费内存,因为必须冗余复制2n 元素(其中n 是两个序列中较短的长度)。可以对符合Sequence的类型进行排序,包括Zip2Sequence
  • @AlexanderMomchliov 您可以对序列进行排序,但不能就位。他试图将排序后的序列重新分配回 Zip2Sequence 变量。这就是问题所在。排序后的序列是一个数组,因此他无法将其分配回 Zip2Sequence。我的回答从一个数组开始,排序后可以赋值回数组变量。
【解决方案2】:

你不能使用sorted(),因为元组类型(MyClass1, MyClass2)不符合Comparable,所以排序器不知道如何排序你的元组。您也不能添加增加一致性的扩展,因为元组不能有扩展或符合协议。

但是,您可以使用sorted(by:),这需要您提供一个定义元素之间排序的闭包。

class MyClass1 {
    var id: Int
    init(id:Int) { self.id = id }
}

class MyClass2 {
    var id2: Int
    init(id2:Int) { self.id2 = id2 }
}
let array1 = [MyClass1(id:4), MyClass1(id:3), MyClass1(id:2), MyClass1(id:1)]
let array2 = [MyClass2(id2:1), MyClass2(id2:2), MyClass2(id2:3), MyClass2(id2:4)]
let tuples = zip(array1, array2)

let sortedTuples = tuples.sorted{ $0.1.id2 > $1.1.id2 }

print(sortedTuples)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多