Tworzenie tablicy liczb całkowitych w iOS

98

Jeśli chcesz utworzyć tablicę liczb całkowitych, czy możesz użyć NSInteger? Czy musisz używać numeru NSNumber? Jeśli tak, to dlaczego?

neuromancer
źródło
Co chcesz zrobić ze swoją tablicą liczb całkowitych?
dreamlax,
Niepewny. Właśnie gdzieś usłyszałem, że musisz użyć NSNumber dla tablic, więc zastanawiałem się nad tym.
neuromanca

Odpowiedzi:

159

Możesz użyć zwykłej starej tablicy C:

NSInteger myIntegers[40];

for (NSInteger i = 0; i < 40; i++)
    myIntegers[i] = i;

// to get one of them
NSLog (@"The 4th integer is: %d", myIntegers[3]);

Lub możesz użyć NSArraylub NSMutableArray, ale tutaj będziesz musiał zawinąć każdą liczbę całkowitą wewnątrz NSNumberinstancji (ponieważ NSArrayobiekty są zaprojektowane do przechowywania instancji klas).

NSMutableArray *myIntegers = [NSMutableArray array];

for (NSInteger i = 0; i < 40; i++)
    [myIntegers addObject:[NSNumber numberWithInteger:i]];

// to get one of them
NSLog (@"The 4th integer is: %@", [myIntegers objectAtIndex:3]);

// or
NSLog (@"The 4th integer is: %d", [[myIntegers objectAtIndex:3] integerValue]);
dreamlax
źródło
9
Myślę, że warto zauważyć, że tablice C są tak kłopotliwe w przypadku czegokolwiek innego niż trywialne, jednorazowe użycie, że w rzeczywistości zawinięcie wszelkich tablic, które planujesz zachować, jako NSArrays of NSNumber.
Chuck,
2
Tak, i biorąc pod uwagę [przypuszczalnie] optymalizacje na poziomie eksperckim pod maską NSArray, jestem pewien, że nie poczujesz uderzenia w wydajność.
dreamlax
@dreamlax Zastanawiam się, jaki rodzaj optymalizacji na poziomie eksperta kryje się za NSArray? Inteligentna alokacja pamięci, która prawdopodobnie podwaja rozmiar przydzielonej pamięci po osiągnięciu limitu?
Ben Sinclair
2
@Andy: Spójrz na rzeczywiste źródło CFArray tutaj i sprawdź testy porównawcze tutaj . To trochę mądrzejsze niż początkowo sądzisz.
dreamlax
Zakładając, że ta tablica jest po prostu używana w metodzie, nie ma problemów z używaniem tablicy C składającej się z NSIntegers? Po prostu podwójne sprawdzenie ...
Dan Rosenstark
58

Tablica C:

NSInteger array[6] = {1, 2, 3, 4, 5, 6};

Tablica Objective-C:

NSArray *array = @[@1, @2, @3, @4, @5, @6];
// numeric values must in that case be wrapped into NSNumbers

Swift Array:

var array = [1, 2, 3, 4, 5, 6]

To też jest poprawne:

var array = Array(1...10)

Uwaga: tablice są silnie wpisywane w języku Swift; w takim przypadku kompilator wnioskuje z treści, że tablica jest tablicą liczb całkowitych. Możesz też użyć tej jawnej składni:

var array: [Int] = [1, 2, 3, 4, 5, 6]

Gdybyś chciał mieć tablicę Doubles, użyłbyś:

var array = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] // implicit type-inference

lub:

var array: [Double] = [1, 2, 3, 4, 5, 6] // explicit type
Frédéric Adda
źródło
1
Jaka byłaby równoważna składnia „@number” dla ujemnej liczby całkowitej?
Ziofil
5

Jeśli chcesz używać NSArray, potrzebujesz klasy Objective-C, aby w nim umieścić - stąd wymóg NSNumber.

To powiedziawszy, Obj-C nadal jest C, więc możesz używać zwykłych tablic C i przechowywać zwykłe liczby int zamiast NSNumbers, jeśli chcesz.

Dennis Munsie
źródło
4

Możesz użyć CFArray zamiast NSArray . Oto artykuł wyjaśniający, jak to zrobić.

CFMutableArrayRef ar = CFArrayCreateMutable(NULL, 0, NULL);
for (NSUInteger i = 0; i < 1000; i++)
{
  CFArrayAppendValue(ar, (void*)i);
}
CFRelease(ar); /* Releasing the array */

To samo dotyczy wersji CoreFoundation innych kontenerów.

coyotte508
źródło
3
Jeśli istnieje przewaga używania CFArray nad NSArray, nie widzę tego. NSArray TO CFArray pod maską; to jest po prostu trudne.
David Gish
1
@Cryptognome tutaj jest mała różnica, CFArray nie zachowa ani nie zwolni niczego, ponieważ został utworzony bez wywołań zwrotnych. Zgadzam się jednak, wydaje się, że nie ma żadnej korzyści.
dreamlax
3

Jeśli kolejność liczb całkowitych nie jest wymagana i jeśli istnieją tylko unikalne wartości

możesz także użyć NSIndexSet lub NSMutableIndexSet Będziesz mógł łatwo dodawać i usuwać liczby całkowite lub sprawdzić, czy twoja tablica zawiera liczbę całkowitą z

- (void)addIndex:(NSUInteger)index
- (void)removeIndex:(NSUInteger)index
- (BOOL)containsIndexes:(NSIndexSet *)indexSet

Sprawdź dokumentację, aby uzyskać więcej informacji.

didier_v_
źródło
2
To okropny pomysł. Oto fragment z dokumentacji firmy Apple: Nie należy używać zestawów indeksów do przechowywania dowolnego zbioru wartości całkowitych, ponieważ zestawy indeksów przechowują indeksy jako posortowane zakresy. Dzięki temu są bardziej wydajne niż przechowywanie zbioru pojedynczych liczb całkowitych. Oznacza to również, że każda wartość indeksu może pojawić się tylko raz w zestawie indeksów.
Rudolf Adamkovič
1
Zgadzam się i dlatego swoją odpowiedź zacząłem od ostrzeżenia. Znam jednak ludzi, którzy zadawali to pytanie o tablice liczb całkowitych i potrzebowali zestawu indeksów. Dlatego podałem tę alternatywną odpowiedź.
didier_v_
Co jest złego w zwykłym NSSet(i używaniu liczb całkowitych zapakowanych w NSNumber)?
dreamlax
@dreamlax narzut, ale ogólnie rzecz biorąc, ludzie zadający takie pytania nie radzą sobie z C i po prostu mają niewiele numerów do przechowywania, więc NSArray lub NSSet muszą być najlepsze.
Ben Sinclair
2

Myślę, że o wiele łatwiej jest używać numerów NS. To wszystko, co musisz zrobić:

NSNumber *myNum1 = [NSNumber numberWithInt:myNsIntValue1];
NSNumber *myNum2 = [NSNumber numberWithInt:myNsIntValue2];
.
.
.
NSArray *myArray = [NSArray arrayWithObjects: myNum1, myNum2, ..., nil];
Neeku
źródło
ale co, jeśli twoja tablica ma 10 lub 100 liczb?
Henson
1
Możesz użyć forlub po prostu innej tablicy dla liczb, a następnie arrayWithArray.
Neeku