flat_list = [item for sublist in l for item in sublist]
, что означает:
for sublist in l:
for item in sublist:
flat_list.append(item)
быстрее, чем ярлыки, опубликованные до сих пор. (l
- список сгладить.)
Вот соответствующая функция:
flatten = lambda l: [item for sublist in l for item in sublist]
Для подтверждения, как всегда, вы можете использовать модуль timeit
в стандартная библиотека:
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 3: 1.1 msec per loop
Объяснение: ярлыки на основе +
(включая подразумеваемое использование в sum
), по необходимости, O(L**2)
, когда есть L подписок - как промежуточный список результатов продолжает увеличиваться, на каждом шаге создается новый объект промежуточного результирующего списка, и все элементы предыдущего промежуточного результата должны быть скопированы (а также несколько новых добавленных в конце). Таким образом (для простоты и без фактической потери общности) скажем, что у вас есть L подсписок из I предметов каждый: первые предметы I копируются взад и вперед L-1 раз, второй I - L-2 раза и т. Д .; общее количество экземпляров: I умножает сумму x для x от 1 до L, т. е. I * (L**2)/2
.
Понимание списка только генерирует один список, один раз и копирует каждый элемент (из его оригинальное место проживания в списке результатов) также ровно один раз.
Как и Sun Tzu сказал : лучше побеждать без боя . В моем случае всякий раз, когда я вижу такое сообщение об ошибке (т. Е. Несоответствие между добавленными строками и т. Д.). Я даже не отлаживаю ничего .. Я просто не делаю дополнительный вызов, где я перезагружаю строки и т. Д., Это 99% случаи, когда эта ошибка происходит.
Это распространенный сценарий, когда эта ошибка происходит: у меня есть UINavigationController
, и у нее есть UITableView
, когда я нажимаю на строку, она нажимает новый UITableView
и так далее. Эта ошибка всегда случается со мной, когда я выхожу последним UITableview
и возвращаюсь к UITableView
перед этим, на этом этапе я делаю ненужный вызов функции loadIt
, которая в основном вставляет строки и переадресует UITableView
,
Причина этого в том, что я ошибочно помещаю функцию loadIt в viewDidAppear:animated
, а не в viewDidLoad
. viewDidAppear:animated
вызывается каждый раз, когда отображается UITableView
, viewDidLoad
вызывается только один раз.
Просто проверьте, что вы вызываете [yourTableView reloadData]; после изменения массива значений.
Я помещаю каждый элемент раздела в разделенные массивы. Затем поместите их в другой массив (arrayWithArray). Мое решение здесь для этой проблемы:
[quarantineMessages removeObject : message];
[_tableView beginUpdates];
if([[arrayWithArray objectAtIndex: indPath.section] count] > 1)
{
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indPath] withRowAnimation:UITableViewRowAnimationBottom];
}
else
{
[_tableView deleteSections:[NSIndexSet indexSetWithIndex:indPath.section]
withRowAnimation:UITableViewRowAnimationFade];
}
[_tableView endUpdates];
Не забудьте обновить массив, который определяет numberOfRowsInSection. Он должен быть обновлен до того, как вы анимируете и удалите
. Мы проверяем, будет ли количество строк в секции равным 1, потому что нам нужно будет удалить весь раздел.
Поправьте меня, если кто-нибудь сможет сделайте этот ответ более ясным.
[self.tableView beginUpdates];
if ([tableView numberOfRowsInSection:indexPath.section] == 1) {
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
} else {
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView endUpdates];
Если вы используете NSFetchedResultsController
, как я, и обновляете данные в фоновом потоке, не забудьте начинать и заканчивать обновления в делетете:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
При удалении строк помните, что он также проверяет разделы при обновлении в:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
Если вы хотите удалить строку, которая является последним элементом в разделе, вам нужно удалить весь раздел вместо этого (в противном случае это может привести к неправильному подсчету раздела и выбросить это исключение).
Я не вижу причины для того, чтобы вы показали нам эту часть кода. Ваша ошибка должна быть связана с этой частью вашего кода. Предполагаю, что
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
Возможно, вы ошибаетесь в одном из этих методов источника данных. В настоящее время невозможно сказать, что именно не так, но я предполагаю, что это может быть что-то вроде: вы говорите в виде таблицы в numberOfRowsInSection
, что хотите зарезервировать и настроить n строки и в cellForRowAtIndexPath
, вы тогда обрабатываете только строки n - 1 .
Извините, что этот ответ не может быть таким точным, каким он должен быть. Если вы покажете нам свою реализацию вашего источника данных, было бы гораздо проще рассказать, что происходит.
У меня была та же проблема с базой данных Core. Если вы используете много FRC, вам просто нужно перезагрузить tableview внутри каждого условия в numberOfSectionsInTableView.
Его может быть одним из методов протокола UITableViewDataSource
. Для
- tableView:numberOfRowsInSection:
он должен вернуть целое число, равное сумме или результату
-insertRowsAtIndexPaths:withRowAnimation:
и / или -deleteRowsAtIndexPaths:withRowAnimation
:
Для
- numberOfSectionsInTableView:
он должен вернуть целое число, равное сумме или результату
-insertRowsAtIndexPaths:withRowAnimation:
и / или -deleteSections:withRowAnimation:
Я только что это случилось со мной, используя Swift и хранилище данных с поддержкой FRC для управления информацией. Добавление простой проверки в операцию удаления для оценки текущего indexPath.section позволило мне избежать постороннего вызова. Я думаю, я понимаю, почему эта проблема возникает ... В основном я загружаю сообщение в верхнюю строку всякий раз, когда мой набор данных пуст. Это создает исключение по одной проблеме, поскольку существует строка faux.
My Solution
... delete my entity, save the datastore and call reloadData on tableView
//next I add this simple check to avoid calling deleteRows when the system (wrongly) determines that there is no section.
if indexPath.section > 0 {
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
У меня была та же ошибка.
Я использовал следующие строки
UINib *myCustomCellNib = [UINib nibWithNibName:@"CustomNib" bundle:nil];
[tableView registerNib:myCustomCellNib forCellReuseIdentifier:@"CustomNib"];
, чтобы зарегистрировать nib в методе viewDidLoad, так как у меня был другой значок, который также был связанных с одним и тем же классом. Следовательно, строка
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"GBFBLoadingCell"];
возвращала ниль, если я не зарегистрировал nib в viewDidLoad.
Моя проблема заключалась в том, что я забыл установить идентификатор в инспекторе атрибутов для моего файла «CustomNib.xib» и «CustomNib ~ iphone.xib». (Или, точнее, я забыл нажать enter после ввода идентификатора в инспекторе атрибутов в XCode, чтобы новое имя не удалось сохранить.)
Надеюсь, что это поможет.
У меня была та же ошибка, которая при попытке с [tableView reloadData]
работала нормально. Ошибка была на самом деле в строке
[TabView insertRowsAtIndexPaths:indexPathsArray withRowAnimation:UITableViewRowAnimationRight];
. Когда я попытался проверить значения indexPath, они были неверны по мере необходимости.
Я исправил это, изменив значения в indexPathsArray
.
Надеюсь, что это поможет.