2016-10-20 5 views
4

Was ist ein Anwendungsfall für die Sammlung underestimateCount. Documentation sagt, dass es die gleiche Komplexität wie Standard Collection count hat.Swift Collection unterschätztCount-Nutzung

Ich habe es Erklärung gesehen:

/// Returns a value less than or equal to the number of elements in 
/// `self`, *nondestructively*. 
/// 
/// - Complexity: O(N). 
public func underestimateCount() -> Int 

Aber es macht mir nichts gesagt, wann sollte ich es verwenden und aus welchem ​​Grund.

+1

Mögliches Duplikat von [Wie holt man die Elementanzahl eines Typs, der \ SequenzTyp \? Entspricht?] (Http://stackoverflow.com/questions/28752743/how-does-one-retrieve-the- element-count-of-type-konform zum Sequenztyp). Die Antwort in den verlinkten Q & A beschreibt, dass wir einige 'Sequence' zählen müssen: s müssen wir iterativ seinen Generator benutzen (swift 3: Iterator). Wenn Sie den Iterator verwenden, um die Anzahl der Elemente explizit zu zählen, wird die Sequenz in einigen Fällen tatsächlich konsumiert und zerstört. 'subsomateCount()' verspricht, eine Zählung zurückzugeben, die nicht größer als die tatsächliche ist. – dfri

+0

... und wie auch in der Antwort beschrieben, wird 'subsumateCount() 'für Sequenzen, die Sammlungen sind, tatsächlich die tatsächliche Anzahl zurückgeben. – dfri

+0

@dfri Diese Frage ist anders, und außerdem beantwortet diese Antwort meine Frage nicht, während Hamish tut. Ähnliches Thema! = Identisch. – KlimczakM

Antwort

7

underestimateCount ist eigentlich eine Forderung des Sequence Protokoll und hat a default implementation, die gerade wieder 0:

public var underestimatedCount: Int { 
    return 0 
} 

für Sequenzen jedoch, die ihre eigene Implementierung von underestimatedCount liefern, kann dies für die Logik nützlich sein, die eine braucht Untergrenze, wie lange die Sequenz ist, ohne dass sie durchlaufen werden muss (bedenken Sie, dass Sequence keine Garantie für eine nicht-destruktive Iteration gibt).

Zum Beispiel kann die map(_:) Methode auf Sequence (see its implementation here) verwendet underestimateCount, um eine Anfangskapazität für die resultierende Anordnung zu reservieren:

public func map<T>(
    _ transform: (Iterator.Element) throws -> T 
) rethrows -> [T] { 

    let initialCapacity = underestimatedCount 
    var result = ContiguousArray<T>() 
    result.reserveCapacity(initialCapacity) 

    // ... 

Dies ermöglicht map(_:) die Kosten der wiederholt auf die result anhängt, zu minimieren, da ein erster Speicherblock (möglicherweise) bereits für ihn reserviert wurde (obwohl es auf jeden Fall erwähnenswert ist, dass ContiguousArray eine exponentielle Wachstumsstrategie hat, die die Kosten des Anhängens amortisiert).

jedoch im Falle eines Collection, the default implementation von underestimateCount tatsächlich gibt nur die Sammlung des count:

public var underestimatedCount: Int { 
    // TODO: swift-3-indexing-model - review the following 
    return numericCast(count) 
} 

die ein O (1) -Operation für Sammlungen werden, die RandomAccessCollection, O (n) entsprechen Andernfalls.

daher aufgrund dieser Standardimplementierung, ein Collection mit ‚s underestimatedCount direkt ist auf jeden Fall weniger verbreitet als ein Sequence mit‘ s, als Collection garantiert zerstörungs Iteration, und in den meisten Fällen underestimatedCount wird nur die count zurück.

Natürlich können benutzerdefinierte Sammlungstypen ihre eigene Implementierung von underestimatedCount - geben eine untere Grenze, wie viele Elemente sie enthalten, in einer möglicherweise effizienteren Weise als ihre Implementierung, die möglicherweise nützlich sein könnte.

2

(Da das doppelte Ziel, schlage ich vor habe, ist etwas veraltet)

In Swift 3, wobei das Verfahren underestimateCount()underestimatedCount durch die berechnete Eigenschaft ersetzt wurde. Wir können für die implementation of the latter for Collection auf den Quellcode haben einen Blick:

/// A value less than or equal to the number of elements in the collection. 
    /// 
    /// - Complexity: O(1) if the collection conforms to 
    /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length 
    /// of the collection. 
    public var underestimatedCount: Int { 
    // TODO: swift-3-indexing-model - review the following 
    return numericCast(count) 
    } 

    /// The number of elements in the collection. 
    /// 
    /// - Complexity: O(1) if the collection conforms to 
    /// `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length 
    /// of the collection. 
    public var count: IndexDistance { 
    return distance(from: startIndex, to: endIndex) 
    } 

Seine offensichtlich, dass underestimatedCount einfach nutzen count für Typen macht Collection konform (es sei denn, diese Typen implementiert ihre eigene Version von underestimatedCount).

+0

Vielen Dank für Ihre Antwort, aber es sagt mir nicht, warum ich es verwenden würde (indem ich das selbst implementiere). – KlimczakM

+0

@KlimczakM für eine 'Collection' (die Sie speziell in Ihrer Frage fragen), sehe ich natürlich keinen technischen Unterschied zwischen den Standard-Implementierungen von' count' und 'unterschätzenCount' (außer für die numerische Darstellung), aber Sie könnte natürlich die Semantik von "unterschätzenCount" verwenden, um Ihre eigene Version davon (für einige benutzerdefinierte Sammlung) zu implementieren, wo Sie sich erlauben könnten, tatsächlich eine Zählung zurückzugeben, die nicht die tatsächliche ist (wenn sich das jemals drehen würde) für Ihre benutzerdefinierte Sammlung nützlich sein). – dfri

+0

... aber ich glaube, dass der interessante Anwendungsfall für 'unterschätzterZahl' für Typen ist, die Sequenzen sind (aber keine Sammlung), insbesondere mit den neuen 'Sequenzfunktionen' (http://swiftdoc.org/v3.0/) func/sequence /), die verwendet werden kann, um eine stream-artige Sequenz zu erzeugen, die nicht notwendigerweise endlich ist. Für benutzerdefinierte Sequenzen von Ihnen könnte "unterschätzte Anzahl" natürlich nützliche Anwendungen haben (nicht konsumierende Zählung). – dfri