假设我有一个自定义类的数组[Player]
,每个类都包含一个名为player.position
我还有一个任意值数组,称为positionOrders
,如下所示:
let positionOrders = ["QB", "WR", "RB", "TE"]
我的目标是对[Player]
所有QB 进行排序,然后再对所有WR,RB和TE 进行排序。
我当前的操作方式是遍历中的每个元素positionOrders
,然后遍历所有播放器以附加到新数组。但是,我想不出一种更简单(更有效)的方法来做到这一点。非常感谢任何提示或指示。谢谢。
编辑: 我原来的方法是狗屎。这篇文章吸引了很多人的注意力,所以现在是应该给予更多关注和改进的时候了。
从根本上讲,问题很容易。我们有两个元素,还有一个数组(或任何ordered
Collection
),它们的相对顺序决定了它们的排序顺序。对于每个元素,我们在有序集合中找到其位置,然后比较两个索引以确定哪个“更大”。
但是,如果我们天真地进行线性搜索(例如Array.firstIndex(of:)
),我们将获得非常糟糕的性能(O(array.count)
),尤其是在固定排序非常大的情况下。为了解决这个问题,我们可以构造一个Dictionary
,将元素映射到它们的索引。该词典提供快速O(1)
查找,非常适合这项工作。
正是HardCodedOrdering
这样。它根据元素的顺序预先计算出一个字典,并提供一个比较2个元素的接口。更好的是,可以将其配置为以未知顺序对遇到的元素做出不同的响应。它可以将它们放在其他所有事物之前,之后,或者完全崩溃(默认行为)之前。
HardCodedOrdering
public struct HardCodedOrdering<Element> where Element: Hashable {
public enum UnspecifiedItemSortingPolicy {
case first
case last
case assertAllItemsHaveDefinedSorting
}
private let ordering: [Element: Int]
private let sortingPolicy: UnspecifiedItemSortingPolicy
public init(
ordering: Element...,
sortUnspecifiedItems sortingPolicy: UnspecifiedItemSortingPolicy = .assertAllItemsHaveDefinedSorting
) {
self.init(ordering: ordering, sortUnspecifiedItems: sortingPolicy)
}
public init<S: Sequence>(
ordering: S,
sortUnspecifiedItems sortingPolicy: UnspecifiedItemSortingPolicy = .assertAllItemsHaveDefinedSorting
) where S.Element == Element {
self.ordering = Dictionary(uniqueKeysWithValues: zip(ordering, 1...))
self.sortingPolicy = sortingPolicy
}
private func sortKey(for element: Element) -> Int {
if let definedSortKey = self.ordering[element] { return definedSortKey }
switch sortingPolicy {
case .first: return Int.min
case .last: return Int.max
case .assertAllItemsHaveDefinedSorting:
fatalError("Found an element that does not have a defined ordering: \(element)")
}
}
public func contains(_ element: Element) -> Bool {
return self.ordering.keys.contains(element)
}
// For use in sorting a collection of `T`s by the value's yielded by `keyDeriver`.
// A throwing varient could be introduced, if necessary.
public func areInIncreasingOrder<T>(by keyDeriver: @escaping (T) -> Element) -> (T, T) -> Bool {
return { lhs, rhs in
self.sortKey(for: keyDeriver(lhs)) < self.sortKey(for: keyDeriver(rhs))
}
}
// For use in sorting a collection of `Element`s
public func areInIncreasingOrder(_ lhs: Element, rhs: Element) -> Bool {
return sortKey(for: lhs) < sortKey(for: rhs)
}
}
let rankOrdering = HardCodedOrdering(ordering: "Private", "Lieutenant", "Captain", "Admiral") // ideally, construct this once, cache it and share it
let someRanks = [
"Admiral", // Should be last (greatest)
"Gallactic Overlord", // fake, should be removed
"Private", // Should be first (least)
]
let realRanks = someRanks.lazy.filter(rankOrdering.contains)
let sortedRealRanks = realRanks.sorted(by: rankOrdering.areInIncreasingOrder) // works with mutating varient, `sort(by:)`, too.
print(sortedRealRanks) // => ["Private", "Admiral"]
问题内容: 在PHP中可以做这样的事情吗?您将如何编写函数?这是一个例子。顺序是最重要的。 我想做类似的事情 因为最后我使用了foreach()并且它们的顺序不正确(因为我将值附加到需要正确顺序的字符串中,而且我事先也不知道所有的数组键/值)。 我看过PHP的内部数组函数,但似乎只能按字母或数字排序。 问题答案: 只需使用或即可。通过以给定的数组(按正确的顺序)开始并用实际数组中的数据覆盖/添加键
因此,我试图学习如何为类项目排序数组。我想知道如何对一个数组进行排序,从而对另一个数组进行排序。在下面的代码中,我可以对年份数组进行排序,但我如何才能使更改这一数组将名称和艺术家数组都更改为它们排列的数组呢?此外,如果你有任何建议,让代码对眼睛不那么苛刻,请告诉我,我正在努力掌握这个概念。
问题内容: 是否可以对看起来像这样的数组进行排序和重新排列: 匹配此数组的安排: 不幸的是,我没有任何要跟踪的ID。我将需要优先处理items-array,以使其尽可能接近sortingArr。 更新: 这是我正在寻找的输出: 任何想法如何做到这一点? 问题答案: 就像是: 这是一个较短的代码,但是会破坏数组:
问题内容: 从这个问题的答案(使用一个较少的内存,沿着一个特定轴对另一个numpy数组进行排序)中,我学习了如何根据另一个numpy数组的值对多维numpy数组进行排序,而又不创建太多额外的数组。 但是,仅当数组和具有相同形状时才有效。我的数组是一维数组,但数组是ND数组(未指定N)。通过一维数组的值在特定轴上对数组进行排序是一种好方法(高效)吗? 问题答案: 使用与关键字参数: 如果要使用花式索
问题内容: 我有多个数组,我想根据其中一个的排序顺序对所有数组进行排序,如下所示: 我希望函数执行后,数组将如下所示: 问题答案: 您可以执行以下操作:首先根据键控数组的索引的索引对它们进行索引的值对它们进行排序,然后使用: 如果要在任何类型的集合上使它通用(但仍以与std lib集合算法相同的样式返回数组): 以及带有自定义比较器的版本:
我有多个数组,我想根据其中一个数组的排序顺序对所有数组进行排序,如下所示: 我预计函数执行后的数组将如下所示: