将排序列表拆分为两个列表
我正在尝试将已排序的整数列表拆分为两个列表。第一个列表包含 n
下的所有整数,第二个列表包含 n
上的所有整数。请注意,n
不必位于原始列表中。
我可以轻松地执行此操作:
under = []
over = []
for x in sorted_list:
if x < n:
under.append(x)
else
over.append(x)
但似乎应该可以以更优雅的方式执行此操作,因为知道列表已排序。 takewhile
和 dropwhile
来自 itertools< /a> 听起来像是解决方案,但随后我会迭代列表两次。
从功能上讲,我能做的最好的事情是:
i = 0
while sorted_list[i] < n:
i += 1
under = sorted_list[:i]
over = sorted_list[i:]
但我什至不确定它是否真的比仅仅迭代列表两次更好,而且它绝对不是更优雅。
我想我正在寻找一种方法来获取 takewhile
返回的列表和剩余的列表,也许是成对的。
I'm trying to split a sorted integer list into two lists. The first list would have all ints under n
and the second all ints over n
. Note that n
does not have to be in the original list.
I can easily do this with:
under = []
over = []
for x in sorted_list:
if x < n:
under.append(x)
else
over.append(x)
But it just seems like it should be possible to do this in a more elegant way knowing that the list is sorted. takewhile
and dropwhile
from itertools sound like the solution but then I would be iterating over the list twice.
Functionally, the best I can do is this:
i = 0
while sorted_list[i] < n:
i += 1
under = sorted_list[:i]
over = sorted_list[i:]
But I'm not even sure if it is actually better than just iterating over the list twice and it is definitely not more elegant.
I guess I'm looking for a way to get the list returned by takewhile
and the remaining list, perhaps, in a pair.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这里正确的解决方案是
bisect
模块。使用 bisect.bisect 查找 n 右侧的索引(如果缺失,则查找将插入的索引),然后围绕该点进行切片:将会是
O(n)
(毕竟你必须复制元素),比较通常比简单的指针复制(和相关的引用计数更新)更昂贵,并且bisect
减少了排序后的比较工作list
到O(log n)
,因此这通常(在较大的输入上)会击败简单地逐个元素迭代和复制,直到找到分割点。使用
bisect.bisect_left
(查找n
的最左边索引)而不是bisect.bisect
(相当于bisect.bisect_right
code>) 如果您希望n
最终位于over
而不是under
。The correct solution here is the
bisect
module. Usebisect.bisect
to find the index to the right ofn
(or the index where it would be inserted if it's missing), then slice around that point:While any solution is going to be
O(n)
(you do have to copy the elements after all), the comparisons are typically more expensive than simple pointer copies (and associated reference count updates), andbisect
reduces the comparison work on a sortedlist
toO(log n)
, so this will typically (on larger inputs) beat simply iterating and copying element by element until you find the split point.Use
bisect.bisect_left
(which finds the leftmost index ofn
) instead ofbisect.bisect
(equivalent tobisect.bisect_right
) if you wantn
to end up inover
instead ofunder
.我将使用以下方法,找到索引并使用切片在
under
和over
创建:输出(与您的代码相同):
编辑:据我了解,这里错误的问题是找到最近索引的适应性解决方案:
输出:
I would use following approach, where I find the index and use slicing to create
under
andover
:Output (same as with your code):
Edit: As I understood the question wrong here is an adapted solution to find the nearest index:
Output: