Jak mogę określić liczbę przypadków w wyliczeniu Swift?
(Chciałbym uniknąć ręcznego wyliczania wszystkich wartości lub używania starej „ sztuczki enum_count ”, jeśli to możliwe).
Jak mogę określić liczbę przypadków w wyliczeniu Swift?
(Chciałbym uniknąć ręcznego wyliczania wszystkich wartości lub używania starej „ sztuczki enum_count ”, jeśli to możliwe).
Począwszy od Swift 4.2 (Xcode 10) możesz zadeklarować zgodność z CaseIterable
protokołem, działa to dla wszystkich wyliczeń bez powiązanych wartości:
enum Stuff: CaseIterable {
case first
case second
case third
case forth
}
Liczba przypadków jest teraz po prostu uzyskiwana za pomocą
print(Stuff.allCases.count) // 4
Aby uzyskać więcej informacji, zobacz
Mam wpis na blogu, który zawiera bardziej szczegółowe informacje na ten temat, ale dopóki surowy typ wyliczenia jest liczbą całkowitą, możesz dodać liczbę w ten sposób:
źródło
case A=1, B=3
?enum
posiadaniaInt
surowej wartości, o której zapomniałeś wspomnieć: Szybkie wyliczanie z Int surowymi wartościami nie muszą zaczynać się od 0 (chociaż jest to zachowanie domyślne), a ich surowe wartości mogą być dowolne, nie mają zwiększać o 1 (nawet jeśli jest to zachowanie domyślne).Aktualizacja Xcode 10
Przyjęcie
CaseIterable
protokołu w wyliczeniu, zapewnia onallCases
właściwość statyczną, która zawiera wszystkie przypadki wyliczania jakoCollection
. Wystarczy użyć jegocount
właściwości, aby dowiedzieć się, ile przypadków ma wyliczenie.Zobacz przykład Martina (i głosuj raczej na jego odpowiedzi niż moje)
Ostrzeżenie : poniższa metoda wydaje się już nie działać.
Nie znam żadnej ogólnej metody liczenia liczby przypadków wyliczania. Zauważyłem jednak, że
hashValue
właściwość przypadków wyliczeniowych jest przyrostowa, zaczynając od zera, i według kolejności określonej przez porządek, w którym przypadki są zadeklarowane. Tak więc skrót ostatniego wyliczenia plus jeden odpowiada liczbie przypadków.Na przykład z tym wyliczeniem:
count
zwraca 4.Nie mogę powiedzieć, czy to reguła, czy zmieni się ona w przyszłości, więc używaj na własne ryzyko :)
źródło
hashValues
tych rzeczach; wiemy tylko, że jest to jakaś losowa unikalna wartość - może w przyszłości bardzo łatwo ulec zmianie w zależności od szczegółów implementacyjnych kompilatora; ale ogólnie niepokojący jest brak wbudowanej funkcji liczenia.case ONE = 0
, można następnie wymienićhashValue
zrawValue
.static var count = 4
niż pozostawić swoje przeznaczenie w losie przyszłych wdrożeń SwiftDefiniuję protokół wielokrotnego użytku, który automatycznie wykonuje licznik spraw na podstawie podejścia opublikowanego przez Nate Cook.
Następnie mogę ponownie użyć tego protokołu, na przykład w następujący sposób:
źródło
count++
na,count+=1
ponieważ++
notacja zostanie usunięta w Swift 3static var caseCount: Int { get }
? skąd ta potrzebastatic func
?case A=1, B=3
?0
i nie miały żadnych luk.Utwórz statyczną tablicę allValues, jak pokazano w tej odpowiedzi
Jest to również pomocne, gdy chcesz wyliczyć wartości i działa dla wszystkich typów Enum
źródło
static let count = allValues.count
. WallValues
razie potrzeby możesz ustawić prywatny.Jeśli implementacja nie ma nic przeciwko używaniu wyliczeń całkowitych, możesz dodać dodatkową wartość członka wywoływaną w
Count
celu reprezentowania liczby członków w wyliczeniu - patrz przykład poniżej:Teraz możesz uzyskać liczbę członków w wyliczeniu, dzwoniąc,
TableViewSections.Count.rawValue
co zwróci 2 dla powyższego przykładu.Podczas obsługi wyliczenia w instrukcji switch upewnij się, że rzuciłeś błąd asercji, gdy napotkasz
Count
członka, którego się nie spodziewasz:źródło
Ten rodzaj funkcji może zwrócić liczbę twojego wyliczenia.
Swift 2 :
Swift 3 :
źródło
enum
jest równieżHashable
tego samego typu.liczyć:
eEventTabType.allValues.count
indeks:
objeEventTabType.index
Cieszyć się :)
źródło
Hej wszystkim, a co z testami jednostkowymi?
W połączeniu z rozwiązaniem Antonio:
w głównym kodzie daje O (1) plus dostajesz test negatywny, jeśli ktoś doda przypadek wyliczenia
five
i nie zaktualizuje implementacjicount
.źródło
Ta funkcja opiera się na 2 nieudokumentowanych bieżących zachowaniach (Swift 1.1)
enum
:enum
jest tylko indeksemcase
. Jeśli liczba przypadków wynosi od 2 do 256, jest toUInt8
.enum
rzutowano bit z niepoprawnego indeksu wielkości liter,hashValue
to jest0
Korzystaj więc na własne ryzyko :)
Stosowanie:
źródło
Napisałem proste rozszerzenie, które daje wszystkim wyliczeniom, w których surową wartością jest liczba całkowita,
count
właściwość:Niestety daje
count
właściwośćOptionSetType
tam, gdzie nie będzie działać poprawnie, więc oto inna wersja, która wymaga jawnej zgodności zCaseCountable
protokołem dla każdego wyliczenia, które przypadki chcesz policzyć:Jest bardzo podobny do podejścia opublikowanego przez Toma Pelaia, ale działa ze wszystkimi typami liczb całkowitych.
źródło
Oczywiście nie jest dynamiczny, ale do wielu zastosowań możesz sobie poradzić dzięki statycznemu var dodanemu do twojego Enum
static var count: Int{ return 7 }
a następnie użyj go jako
EnumName.count
źródło
LUB
* W Swift 4.2 (Xcode 10) można używać:
źródło
W moim przypadku użycia w bazie kodu, w której wiele osób może dodawać klucze do wyliczenia, a wszystkie te przypadki powinny być dostępne we właściwości allKeys, ważne jest, aby wszystkie klucze były sprawdzane względem kluczy w tym wyliczeniu. Ma to na celu uniknięcie sytuacji, gdy ktoś zapomni dodać swój klucz do listy wszystkich kluczy. Dopasowanie liczby tablicy allKeys (najpierw utworzonej jako zestaw, aby uniknąć duplikatów) do liczby kluczy w wyliczeniu zapewnia, że wszystkie są obecne.
Niektóre z powyższych odpowiedzi pokazują sposób osiągnięcia tego w Swift 2, ale żadna nie działa w Swift 3 . Oto sformatowana wersja Swift 3 :
W zależności od przypadku użycia możesz po prostu uruchomić test w fazie rozwoju, aby uniknąć narzutu związanego z używaniem wszystkich klawiszy na każde żądanie
źródło
Dlaczego sprawiasz, że wszystko jest tak skomplikowane? Najprostszym licznikiem Int enum jest dodanie:
case Count
Na końcu. I ... altówka - teraz masz liczyć - szybko i prosto
źródło
0
i nie miały żadnych przerw w sekwencji.Jeśli nie chcesz opierać kodu na ostatnim wyliczeniu, możesz utworzyć tę funkcję w swoim wyliczeniu.
źródło
Wersja Swift 3 działająca z
Int
wyliczeniami typów:Kredyty: Na podstawie odpowiedzi Bzz i Nate Cook.
Rodzajowy
IntegerType
(w Swift 3 przemianowany naInteger
) nie jest obsługiwany, ponieważ jest to mocno rozdrobniony typ ogólny, który nie ma wielu funkcji.successor
nie jest już dostępny w Swift 3.Pamiętaj, że komentarz od Code Commander do odpowiedzi Nate Cooks jest nadal aktualny:
O ile wiem, obecnie nie ma możliwości obejścia tego problemu jako rozszerzenia protokołu (i braku implementacji w każdym wyliczeniu, jak to zrobił Nate Cook) z powodu statycznych właściwości przechowywanych, które nie są obsługiwane w typach ogólnych.
W każdym razie dla małych wyliczeń nie powinno to stanowić problemu. Typowy przypadek użycia byłby
section.count
dlaUITableViews
jak już wspomniano przez Zorayr.źródło
Rozszerzając odpowiedź Matthieu Rieglera, jest to rozwiązanie dla Swift 3, które nie wymaga użycia ogólnych, i można je łatwo wywołać za pomocą typu wyliczeniowego z
EnumType.elementsCount
:źródło
Rozwiązałem ten problem dla siebie, tworząc protokół (EnumIntArray) i globalną funkcję narzędziową (enumIntArray), które bardzo łatwo dodają zmienną „All” do dowolnego wyliczenia (używając swift 1.2). Zmienna „all” będzie zawierać tablicę wszystkich elementów w wyliczeniu, dzięki czemu można użyć all.count do zliczenia
Działa tylko z wyliczeniami, które używają surowych wartości typu Int, ale być może może stanowić inspirację dla innych typów.
Zajmuje się także „luką w numeracji” i „nadmiernym czasem na iterację” problemów, które przeczytałem powyżej i gdzie indziej.
Chodzi o to, aby dodać protokół EnumIntArray do enum, a następnie zdefiniować zmienną statyczną „all”, wywołując funkcję enumIntArray i podając jej pierwszy element (i ostatni, jeśli w numeracji występują luki).
Ponieważ zmienna statyczna jest inicjalizowana tylko raz, narzut związany z przechodzeniem przez wszystkie wartości surowe uderza w twój program tylko raz.
przykład (bez przerw):
przykład (z przerwami):
Oto kod, który go implementuje:
źródło
Lub możesz po prostu zdefiniować
_count
wyliczenie zewnętrzne i dołączyć je statycznie:W ten sposób, bez względu na to, ile utworzysz wyliczeń, zostanie ono utworzone tylko raz.
(jeśli
static
tak, usuń tę odpowiedź )źródło
Poniższa metoda pochodzi z CoreKit i jest podobna do odpowiedzi sugerowanych przez innych. Działa to z Swift 4.
Musisz po prostu zadzwonić
Weekdays.allValues.count
.źródło
źródło
ale zachowaj ostrożność podczas używania na typach innych niż wyliczanie. Niektóre obejście może być:
źródło
Może używać stałej statycznej, która zawiera ostatnią wartość wyliczenia plus jeden.
źródło
Jest to niewielkie, ale myślę, że lepszym rozwiązaniem O (1) byłoby ( TYLKO jeśli twoje wyliczenie
Int
zaczyna się od x itp.):Aktualnie wybrana odpowiedź, którą nadal uważam, jest najlepszą odpowiedzią dla wszystkich wyliczeń, chyba że pracujesz,
Int
to polecam to rozwiązanie.źródło
guard
jest przeciwCOUNT
i generuje błąd, zwraca wartość false itp., Aby rozwiązać problem dotyczący reprezentacji typów.