Python 初学者求助

2019-03-06 17:26:33 +08:00
 zblc4c4
问题:整数数列列表 a,例如 random.shuffle([i for i in range(10000)])
整数 b,例如 5000
a 中所有小于 b 的元素组成新列表 c,a 中剩余元素组成新列表 d

目标条件:效率最高,计算时间优先,不考虑内存占用

我能想到的两种思路:
1 )使用 for 循环对每个元素判断,append 到对应列表
2 ) c = [x for x in a if x < b] d = [x for x in a if x >= b]
1 中 append 函数严重影响效率,2 中每次比较大小用了 2 遍,因为是新手,经验不足,想不到两全其美的方法,希望能得到大佬指教
3126 次点击
所在节点    Python
26 条回复
dswill
2019-03-06 17:36:04 +08:00
使用 numpy.where()函数试下效果。 注:我也是初学者,不过刚好看到这个,感觉可能用得上。
stebest
2019-03-06 17:37:26 +08:00
我有个问题,为啥不直接 c=random.shuffle([i for i in range(5000)]), d=random.shuffle([i for i in range(5000,10000)])
如果是乱序的话,排个序不是更好分了。
jmc891205
2019-03-06 17:39:02 +08:00
你说的两种方法都可以 都是线性的时间复杂度
没必要纠结 append 或两次比较什么的
airborne007
2019-03-06 17:44:29 +08:00
@stebest random.shuffle 返回的是 None
airborne007
2019-03-06 17:45:33 +08:00
一次循环和先排序再切片,效率都差不多,append 本身也不慢,都是线性复杂度,没必要太纠结。
zblc4c4
2019-03-06 17:48:08 +08:00
@jmc891205 这个函数被调用十万百万次级时,区别就体现了,所以能优化多少是多少,1%也是好的
stebest
2019-03-06 17:49:05 +08:00
@airborne007 没把 c=写到括号里,2333。不过 O(n)时间内,已经是比较好的结果了。
zblc4c4
2019-03-06 17:51:48 +08:00
@stebest 我只是测试用,重点是实现功能
CosimoZi
2019-03-06 17:55:54 +08:00
你想什么呢,组成新列表这个动作只要有,就是 O(n)的复杂度.
myyou
2019-03-06 17:57:30 +08:00
如果数组存的都是存储的都是相同类型可以考虑使用 array 的 append 方法: https://docs.python.org/3.6/library/array.html
jmc891205
2019-03-06 17:58:08 +08:00
@zblc4c4 你应该学习一下为什么大家评价一个算法的快慢是用时间复杂度而不考虑常数
zblc4c4
2019-03-06 18:01:08 +08:00
@CosimoZi 2n 和 n 差距也很大啊,算法没有可改进的地方,编程逻辑是有优化空间的
zblc4c4
2019-03-06 18:02:17 +08:00
@jmc891205 但我希望改进的不是算法,而是算法的实现的优化
zblc4c4
2019-03-06 18:05:16 +08:00
@jmc891205 这两种思路都是有不完美之处的,这个应该是毋庸置疑的,我追求的不仅仅是这个功能的实现,而是借鉴别人的思路,拓宽一下思维
hahastudio
2019-03-06 18:08:17 +08:00
那你可以试试 itertools.groupby
jmc891205
2019-03-06 18:10:02 +08:00
@zblc4c4 在工程上 你就是在做无用功。

不过我再给你提供一个线性时间复杂度的思路吧
你可以参考快排中的 partition 部分 在原 list 上把比 b 小的都交换到 b 之前 比 b 大的都交换到 b 之后
这样既不用 append 也不会比较两次 而且不需要申请额外的内存
rabbbit
2019-03-06 18:12:41 +08:00
这个跟算法没啥关系,就跑一遍就完了.算法一般不考虑是 n 还是 2n,那个 2 直接约掉了.
楼主应该是想问 append 和列表生成式哪个效率高吧.
shyrock
2019-03-06 18:18:54 +08:00
我认为效率最高的方法是先用 sort 排序,然后 bisect 找到切分点。
angryRabbit
2019-03-06 18:30:00 +08:00
我提个思路,直接 copy、遍历、替换为 None

a=list(range(0,5000))
b=2000
c=a.copy()
d=a

for i,elem in enumerate(0,c):
if i>b:
c[i]=None
else:
d[i]=None
zblc4c4
2019-03-06 19:00:54 +08:00
@jmc891205
@angryRabbit
感谢两位提供的思路,我去做一些测试

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/541826

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX