Я предложу рубрику:
1.Соответствуйте стилю существующей кодовой базы.
В большом проекте может быть полезно, если все написано в едином стиле.Для супер-низкоуровневых вещей, таких как итерация списка, это не обязательно имеет большое значение, но если большинство вещей «один» способ выполнить ту же задачу, «другой» способ запутает людей, которые придут позже.
2.Если ваш язык имеет собственную итерацию списка (например, функцию «map»), используйте ее.
В большинстве новых языков есть какой-либо способ выполнить действие со списком в целом, или есть какой-то стандартный способ итерации по списку.списки.
# Python
for x in collection_1:
print(x)
// Javascript
collection_1.forEach(x => console.log(x))
-- Haskell
mapM_ putStrLn collection1
// Go
for _, x := range collection1 {
fmt.Printf("%d\n", x)
}
В C и языках, тесно связанных с ним, индексирование массивов является идиоматическим, поэтому сделайте это , если это обычное соглашение в этом языке .
/* C */
void printList(int *l, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d\n", l[i]);
}
}
3.Понять, что такое тип «список».
Разные языки имеют разные реализации списков по умолчанию с разными характеристиками.Если «список» является односвязным списком (Lisp, Haskell), то итерация по нему элемента за раз и передача «остальной части списка» на самом деле верны.
-- Haskell
-- printAList is a function that takes a list parameter
-- and returns an IO action producing no value in particular.
printAList :: [Int] -> IO ()
-- To print an empty list, do nothing.
printAList [] = return ()
-- To print a non-empty list:
printAList (x:xs) = do
-- Print the first element;
putStrLn (show x)
-- Then print the list of things starting at the second element.
printAList xs
Так как этооднако, для списка с однократной связью выбор элемента по индексу может занять O ( n ) времени, и вы определенно не хотите этого делать.
В некоторых языках «список»начальная позиция плюс длина (массивы в C, слайсы в Go), и в этом случае «создать список остальных» не так уж и дорого, хотя обычно выглядит немного странно.
/* C programmers will look at you funny */
void printList2(int *l, int len) {
for (; len > 0; l++, len--)
printf("%d\n", l[0]); /* or *l */
}
}
// Go: also strange, but not wildly inefficient
func printList(l []int) void {
while (len(l) > 0) {
fmt.Printf("%d\n", l[0])
l = l[1:len(l)]
}
}
Но если «список» - это блок элементов, и для его изменения необходимо скопировать весь список (Python, как предлагает @ Ry- в комментариях), тогда вы определенно не хотите этого;но тогда поиск предметов по индексу относительно дешев.
# Python; this is common to update a list in place
for i in range(len(container_1)):
container_1[i] += 1
4.Осторожно отдайте предпочтение неразрушающим действиям.
На современном оборудовании дорогостоящие вещи - это ввод-вывод, сетевые вызовы и плохие алгоритмы.Небольшая эффективность в основном не имеет значения.Есть ли практическая разница между:
# Python
def doubleListInPlace(l):
for i in range(len(l)):
l[i] *= 2
return l
def doubleListAndCopy(l):
return [2 * x for x in l]
def main():
l = [1, 2, 3]
ll = doubleList...(l)
lll = doubleList...(ll)
print("Doubled list: " + repr(ll))
print("Quadrupled list: " + repr(lll))
Форма immutable ("... andCopy"), конечно же, выделяет дополнительный список, но когда вы перейдете к использованию результата позже, будет меньше сюрпризов, ожидающих, иВы (обычно) не заметите дополнительное распределение.Использование более неизменного стиля также очень полезно при тестировании (вы можете создать тестовое приспособление один раз и повторно использовать его во всех тестах) и для поддержки стека отмены (это ядро «отладчика путешествий во времени» в среде Javascript Redux, дляinstance).
Является ли один подход значительно более дорогим?
Если ваш "нативный" тип списка является односвязным списком, то попытайтесь перебрать его по индексузанимает O ( n ^ 2) времени (вы должны пройти все n элементов, чтобы добраться до последнего, плюс n -1, чтобы добраться до второго-до последнего плюс ...).Если ваш «родной» тип списка основан на массиве или векторе, то работа с подсписками займет O (n ^ 2) времени (вы должны скопировать все n -1 элементов, которые вы еще не обработали),На этот вопрос нет конкретного универсального кросс-языкового ответа.