NSArray Loop для захвата объектов - PullRequest
2 голосов
/ 26 июня 2011

В настоящее время я нахожусь в процессе разработки приложения, которое должно иметь возможность получить два объекта из NSArray и затем сохранить его в другом объекте.

В настоящее время у меня запущен этот быстрый цикл перечисления,

NSUInteger count = 0;
NSUInteger i = count + 1;
for (id item in [section items]) {


    item1 = [section.items objectAtIndex:count];
    item2 = [section.items objectAtIndex:i];

    count++;

}

Теперь я хочу захватить объект в первой позиции и сохранить в item1, а затем вторая позиция будет сохранена в item2. В следующий раз, когда он пройдет цикл, я хочу, чтобы он сохранил объект в третьей позиции в item1, а затем в четвертой позиции в item2 и т. Д.

Кто-нибудь когда-нибудь пытался и достиг этого?

EDIT

Это то, что у меня сейчас есть, я подумал, что лучше всего объяснить, что я делаю, немного глубже, так что дальше. Вот код, который у меня есть сначала, а потом я объясню.

MPSection *section = [self.sections objectAtIndex:indexPath.section];

NSArray *itemArray = [section items];
for (NSUInteger i = 0; (i + 1) < [section.items count]; i += 2) {
    item1 = [itemArray objectAtIndex:i];
    item2 = [itemArray objectAtIndex:i+1];
}

Как вы можете видеть, это выполняется в (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath, так как я хочу взять то, что обычно отображается в первой и второй строке UITableView, и поместить его в одну ячейку, которая разделена на два подпредставления.

Что я нахожу, так это то, что, используя приведенный выше код, он определенно этого не делает. Есть ли более простой способ, которым я могу сделать это, и если так, может кто-то, пожалуйста, сообщите мне об этом. Мне действительно нужно подойти к этому с сохранением памяти и минимальным потреблением времени.

Ответы [ 4 ]

3 голосов
/ 26 июня 2011

Если вы не можете использовать быстрое перечисление здесь, вы можете установить флаг, который позволяет пропустить каждую четную итерацию цикла:

BOOL doThisOne = YES;
NSArray itemArray = [section itemArray];
for (id item in items) {
    if (doThisOne) {
        item1 = item;
        item2 = [itemArray objectAtIndex:1+[itemArray indexOfObject:item]];
    }
    doThisOne = !doThisOne;
}

Примечание: Приведенный выше код вызывает исключение диапазона, если число элементов в массиве нечетное. Некоторые другие ответы избегают этого, но я думаю, что лучший ответ - просто не использовать быстрое перечисление здесь.

Было бы намного проще использовать перечислитель или просто использовать обычный старый цикл for:

NSEnumerator *e = [[section items] objectEnumerator];
while (item = [e nextObject]) {
    item1 = item;
    item2 = [e nextObject];
}

или

NSArray *itemArray = [section items];
for (int i = 0; (i + 1) < [items count]; i += 2) {
    item1 = [items objectAtIndex:i];
    item2 = [items objectAtIndex:i+1];
}
3 голосов
/ 26 июня 2011

Было бы хорошо, если вы можете предварительно обработать это, но если вы не можете сделать это по какой-то причине, то это то, что вы должны сделать,

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    MPSection * section = [self.sections objectAtIndex:section];
    NSInteger   count   = [section.items count];

    return ((count % 2 == 0)? count / 2 : (count / 2 + 1) );
}

И в методе tableView:cellForRowAtIndexPath:,

/* */

MPSection *section = [self.sections objectAtIndex:indexPath.section];

id item1 = [section.items objectAtIndex:(indexPath.row * 2)];
id item2 = ((indexPath.row * 2 + 1) < [section.items count])? [section.items objectAtIndex:(indexPath.row * 2 + 1)] : nil;

/* Use item1 & item2 to fill both the subviews */

Оригинальный ответ

Используйте для этой цели экземпляр NSEnumerator

NSEnumerator *enumerator = [section.items objectEnumerator];
id item1, item2;
while ( (item1 = [enumerator nextObject]) && (item2 = [enumerator nextObject]) ) {
    // Use item1 & item2
}

Поэтому я думаю, что вы должны получить ошибку индексации из границ для упомянутого вами фрагмента.

Overkill

Похоже, возникает вопрос о производительности, поэтому я протестировал три предложенных метода и рассчитал их по времени в цикле, где я их регистрирую.

Enumerator, Fast Enumeration with Object Search, For Loop (50000 elements): 19.253626, 88.269961, 18.767572
Enumerator, Fast Enumeration with Object Search, For Loop (25000 elements): 9.164311, 25.105664, 8.777443
Enumerator, Fast Enumeration with Object Search, For Loop (10000 elements): 3.428265, 6.035876, 3.144609
Enumerator, Fast Enumeration with Object Search, For Loop (5000 elements): 2.010748, 2.548562, 1.980477
Enumerator, Fast Enumeration with Object Search, For Loop (1000 elements): 0.508310, 0.389402, 0.338096
Enumerator, Fast Enumeration with Object Search, For Loop (500 elements): 0.156880, 0.163541, 0.150585
Enumerator, Fast Enumeration with Object Search, For Loop (100 elements): 0.076625, 0.034531, 0.036576
Enumerator, Fast Enumeration with Object Search, For Loop (50 elements): 0.026115, 0.022686, 0.041745

На первый взгляд, циклический подход @ Caleb for может быть лучшим подходом.

1 голос
/ 26 июня 2011
int numItems = [section.items count];

for(int i = 0; i < count; i++) {
    item1 = [section.items objectAtIndex: i];
    item2 = ((i + 1) < count)) ? [section.items objectAtIndex: (i + 1)] : nil;
} 
1 голос
/ 26 июня 2011
for(id item in array){
    if([array indexOfObject:item] % 2 != 0){
     item1 = item;
    }else{
     item2 = item;
    }
}
...