Python - 有效地找到某些东西会在排序列表中出现的位置?

时间:2015-05-14 18:52:20

标签: python sorting

我有一个清单:

x = ['c', 'a', 'e']

我可以对此列表进行排序:

x_sorted = sorted(x)

x_sorted现在是['a', 'c', 'e']

现在假设我有一个新变量y = 'd'

我想知道x_sorted这个新变量会落在哪里。在此示例中,新变量y包含字符串'd',因此它将作为['a', 'c', 'd', 'e']放置在列表的索引2中。我希望尽可能有效地找出这个索引号(因为我必须多次重复这个过程)。

这是我写的一个非常简单的任务:

def f(x_sorted, y):
    new_list = x_sorted[:] + [y]
    return sorted(new_list).index(y)

这给了我正确的答案。

我想知道是否有更好的更有效的方法,因为f将被称为100,000次以上。

提前致谢!

3 个答案:

答案 0 :(得分:9)

您可以使用bisect

from bisect import bisect

l = ['a', 'c', 'e']

print(bisect(l,"d"))
2

将其添加到列表中:

from bisect import insort


l = ['a',"b", 'c', 'e']

insort(l, "d")
print(l)
insort(l, "f")
print(l)

['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e', 'f']

如果您想要更快的插入,可以使用blist维护带有insort的排序列表:

O(log**2 n)  vs  O(n)
来自bisect import insort的

from blist import blist

b = blist(["a", "b", "c", "e"])
insort(b, "f")
insort(b, "d")
print(b)
blist(['a', 'b', 'c', 'd', 'e', 'f'])

还有一个blist.sortedlist列表,您可以使用.add

from blist import sortedlist

l = ['b',"a", 'c', 'e']
b = sortedlist(l)

b.add("f")
print(b)
sortedlist(['a', 'b', 'c', 'e', 'f'])

还有一个sortedcontainers库,其sortedlist实施。

答案 1 :(得分:2)

如果O(n logn)没有更改或不经常更改,您可以对其进行预排序,然后在排序列表中使用二进制搜索。对于每次后续查找,这将导致O(logn)每种加x费用加上>>> x = ['c', 'a', 'e'] >>> y = 'd' >>> sum(y > el for el in x) 2

如果O(n)发生了很大变化,您可以使用线性搜索:

#!/bin/bash
# Peter Black
# alarm.sh
max_percent=94
sleeper=1
frequency=1000
duration=300

# To enable the script:
# chmod u+x alert.sh

# get the total available memory:
function total_memory {
    echo "Total memory available: "
    TOTAL_MEM=$(grep MemTotal /proc/meminfo | awk '{print $2}')
    #Another way of doing that:
    #total_mem=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
    echo "---------- $TOTAL_MEM ---------------"
}


# alarm function params: frequency, duration
# Example:
# _alarm 400 200
_alarm() {
  ( \speaker-test --frequency $1 --test sine )&
  pid=$!
  \sleep 0.${2}s
  \kill -9 $pid
}

function total_available_memory {
    total_available_mem=$(</proc/meminfo grep MemTotal | grep -Eo '[0-9]+')
    total_free_mem=$(</proc/meminfo grep MemFree | grep -Eo '[0-9]+')
    total_used_mem=$((total_available_mem - total_free_mem))
    #percent_used=$((total_available_mem / total_free_mem))
    # print the free memory
    # customize the unit based on the format of your /proc/meminfo
    percent_used=$(printf '%i %i' $total_used_mem $total_available_mem | awk '{ pc=100*$1/$2; i=int(pc); print (pc-i<0.5)?i:i+1 }')

    if [ $percent_used -gt $max_percent ]; then
        echo "TOO MUCH MEMORY IS BEIGN USED!!!!!!!! KILL IT!"
        _alarm $frequency $duration
    fi

    echo "Available: $total_available_mem kb  -  Used: $total_used_mem kb  -  Free: $total_free_mem kb  -  Percent Used: $percent_used %"

}

# RUN THE FUNCTIONS IN AN INFINITE LOOP:
# total_memory

echo "Press [CTRL+C] to stop.."
while :
do
    total_available_memory
    sleep $sleeper
done

这具有if (date1.getTime() <= date.getTime() && date.getTime() <= date2.getTime()) { /* * date is between date1 and date2 (both inclusive) */ } /* * when date1 = 2015-01-01 and date2 = 2015-01-10 then * returns true for: * 2015-01-01 * 2015-01-01 00:00:01 * 2015-01-02 * 2015-01-10 * returns false for: * 2014-12-31 23:59:59 * 2015-01-10 00:00:01 * * if one or both dates are exclusive then change <= to < */ 查找复杂性。

答案 2 :(得分:0)

这肯定不是你在问题中证明的有效方式,在这种情况下你每次都要对它进行排序,因此如果你执行这个动作m次,复杂性将是O(m*n*log(m)),所以首选方法是对其进行一次排序,然后简单地遍历列表以查找索引,这可以在O(n)中完成,但最好的方法是使用二进制搜索,现在您的时间复杂度将降至O(log(n))。对于这类问题,这是最小的复杂性。