我建议一个准则:
一。匹配现有代码库的样式。
在一个大的项目中,如果事情是以一致的风格写的,它会很有帮助。对于超低级的事情,比如列表迭代,这不一定是件大事,但是如果大多数事情都是“一种”方式来完成相同的任务,“另一种”方式会让后来的人感到困惑。
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]);
}
}
三。了解“列表”是什么类型。
不同的语言对具有不同特性的列表有不同的默认实现。如果“list”是一个单独链接的列表(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
不过,由于它是一个单独链接的列表,所以按索引获取一个元素可能需要(
n个
)时间和你绝对不想这样做。
在某些语言中,“list”是一个起始位置加上一个长度(C中的数组,Go中的切片),在这种情况下,“create a list of the rest”并不昂贵,尽管看起来有点奇怪。
/* 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-comments中建议的那样),那么您肯定不希望这样;但是按索引查找项目相对便宜。
# Python; this is common to update a list in place
for i in range(len(container_1)):
container_1[i] += 1
四。温和地选择非破坏性的行动。
在现代硬件上,昂贵的东西是I/O、网络调用和糟糕的算法。小效率基本上无关紧要。以下两项之间是否存在实际差异:
# 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))
一种方法要贵得多吗?
如果您的“原生”列表类型是一个单独链接的列表,那么尝试通过索引遍历它需要(
n个
n个
最后一个元素,加上
-1到倒数第二个,加上。如果“本机”列表类型基于数组或向量,则使用子列表将花费O(n^2)时间(必须全部复制
-1个您尚未处理的项目)。对此没有一个通用的跨语言答案。