首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在swift中仅重新订购集合的一部分?

如何在swift中仅重新订购集合的一部分?
EN

Stack Overflow用户
提问于 2020-06-01 17:17:03
回答 2查看 56关注 0票数 0

我有一个Item数组。该顺序永远不会得到保证,因为集合是从基于其他地方的许多用户操作的API提供的。

但是,我需要按type字段对这个集合进行排序,这样我就可以在其他地方正确地迭代它。

在下面的示例游乐场的情况下,我需要一个遵循以下逻辑的重新排序的集合:

代码语言:javascript
运行
复制
[
  Item(type: .foo),
  Item(type: .bar),

  Item(type: .boo),
  Item(type: .baz),

  Item(type: .boom),
  Item(type: .bang)

]

具体来说,.foo.bar应该是前两项,.boombang将是最后两项。

这些固定项是唯一的,响应中不会存在重复项。

剩下的所有东西都应该在这两个组之间,顺序与原始集合中的顺序相同。

我已经尝试在var output: [Item]中将项目拆分为两个集合,并在索引处插入第二个集合,但是排序仍然是错误的。

我如何才能做到这一点?

代码语言:javascript
运行
复制
import UIKit

enum ItemType: String {
  case foo
  case bar
  case boo
  case baz
  case boom
  case bang
}

struct Item {
  let type: ItemType
}

let props = [
  Item(type: .bang),
  Item(type: .bar),
  Item(type: .baz),
  Item(type: .boo),
  Item(type: .boom),
  Item(type: .foo)
]

/*
 case foo
 case bar
 > ----------- should be ordered in same order as in `props`
 case boom
 case bang
*/

var output: [Item] {
  var fixedPosition: [Item] = []
  var dynamicPosition: [Item] = []

  props.forEach { item in
    if (item.type == .foo || item.type == .bar || item.type == .boom || item.type == .bang ){
      fixedPosition.append(item)
    } else {
      dynamicPosition.append(item)
    }
  }

  var result: [Item] = fixedPosition
  result.insert(contentsOf: dynamicPosition, at: 1)

  return result
}

print(output.map { $0.type })
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-01 17:34:09

您可以为每个枚举案例提供一个int值,并对其进行稳定排序:

代码语言:javascript
运行
复制
func intValue(for itemType: ItemType) -> Int {
    switch itemType {
    case .foo:
        return 0
    case .bar:
        return 1
    case .boo, .baz: // the order of these should remain the same, so they get the same number
        return 2
    case .boom:
        return 3
    case .bang:
        return 4
    }
}

let sorted = props.stableSorted(by: { intValue(for: $0.type) < intValue(for: $1.type) })

stableSort取自this answer by leavez

代码语言:javascript
运行
复制
extension RandomAccessCollection {

    /// return a sorted collection
    /// this use a stable sort algorithm
    ///
    /// - Parameter areInIncreasingOrder: return nil when two element are equal
    /// - Returns: the sorted collection
    public func stableSorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element] {

        let sorted = try enumerated().sorted { (one, another) -> Bool in
            if try areInIncreasingOrder(one.element, another.element) {
                return true
            } else {
                return one.offset < another.offset
            }
        }
        return sorted.map { $0.element }
    }
}
票数 1
EN

Stack Overflow用户

发布于 2020-06-01 19:34:04

实施Comparable协议的ItemType变体:

代码语言:javascript
运行
复制
extension ItemType: Comparable {
    static func < (lhs: ItemType, rhs: ItemType) -> Bool {
        // function returns `true` iff lhs is smaller than res

        // order of cases matters here, switch matches them left-to-right, top-to-bottom
        switch (lhs, rhs) {
        case (.foo, _): // .foo is before everyone else
            return true
        case (_, .foo): // nothing is "smaller" than .foo
            return false
        case (.bar, _):  // .bar can be preceded only by .foo (previous 2 cases handle it)
            return true
        case (_, .bang): // .bang is always last
            return true
        case (.bang, _): // nothing is "bigger" than .bang
            return false
        case (_, .boom): // .boom can be only before .bang (previous 2 cases handle it)
            return true
        default: // otherwise we don't care about comparing items, neither item is "smaller" than other
            return false
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62129078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档