Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-如何检查列表单调性_Python_List_Performance - Fatal编程技术网

Python-如何检查列表单调性

Python-如何检查列表单调性,python,list,performance,Python,List,Performance,检查列表单调性的有效方法是什么?即它具有单调递增或递减的值 示例: [0, 1, 2, 3, 3, 4] # This is a monotonically increasing list [4.3, 4.2, 4.2, -2] # This is a monotonically decreasing list [2, 3, 1] # This is neither 这种方法在列表长度上是O(N) 最好避免使用诸如“增加”或“减少”之类的模棱两可的术语,因为不清楚平

检查列表单调性的有效方法是什么?即它具有单调递增或递减的值

示例:

[0, 1, 2, 3, 3, 4]   # This is a monotonically increasing list
[4.3, 4.2, 4.2, -2]  # This is a monotonically decreasing list
[2, 3, 1]            # This is neither

这种方法在列表长度上是
O(N)

最好避免使用诸如“增加”或“减少”之类的模棱两可的术语,因为不清楚平等是否可以接受。您应该始终使用例如“非递增”(显然相等被接受)或“严格递减”(显然相等被不接受)

def严格递增(L):
返回全部(xy表示x,y表示zip(L,L[1:]))
def不增加(L):
返回全部(x>=y表示x,y在zip中(L,L[1:]))
def非衰减(L):

返回全部(x如果您有大量的数字列表,最好使用numpy,如果您是:

import numpy as np

def monotonic(x):
    dx = np.diff(x)
    return np.all(dx <= 0) or np.all(dx >= 0)
将numpy导入为np
def单调(x):
dx=np.diff(x)
返回np.all(dx=0)

应该可以了。

@6502有完美的列表代码,我只想添加一个适用于所有序列的通用版本:

import operator, itertools

def is_monotone(lst):
    op = operator.le            # pick 'op' based upon trend between
    if not op(lst[0], lst[-1]): # first and last element in the 'lst'
        op = operator.ge
    return all(op(x,y) for x, y in itertools.izip(lst, lst[1:]))
def pairwise(seq):
    items = iter(seq)
    last = next(items)
    for item in items:
        yield last, item
        last = item

def strictly_increasing(L):
    return all(x<y for x, y in pairwise(L))

def strictly_decreasing(L):
    return all(x>y for x, y in pairwise(L))

def non_increasing(L):
    return all(x>=y for x, y in pairwise(L))

def non_decreasing(L):
    return all(x<=y for x, y in pairwise(L))
def成对(seq):
项目=国际热核试验堆(序号)
最后一个=下一个(项目)
对于项目中的项目:
最后一项
最后一项=项目
def严格增加(L):
返回全部(xy代表x,y成对(L))
def不增加(L):
返回全部(x>=y表示x,y成对(L))
def非衰减(L):

return all(x这是一个功能解决方案,它使用复杂度
O(n)
reduce

第二个元素的大小写为假:
[4,2,3,4,5,6,7,8,7]

# my solution .. 
$ python -m timeit "inc = lambda L: reduce(lambda a,b: b if a < b else 9999 , L)!=9999; inc([4,2,3,4,5,6,7,8,7])"
1000000 loops, best of 3: 1.87 usec per loop

# while the other solution:
$ python -m timeit "inc = lambda L: all(x<y for x, y in zip(L, L[1:]));inc([4,2,3,4,5,6,7,8,7])"
100000 loops, best of 3: 2.15 usec per loop
#我的解决方案。。
$python-m timeit“inc=lambda L:reduce(如果a$python-m timeit“inc=lambda L:all(xI在不同的条件下对这个问题的所有答案进行计时,并发现:

  • 如果列表已经单调增加,那么排序是最快的
  • 如果列表是无序的/随机的,或者如果无序元素的数量大于~1,则排序速度最慢。当然,无序越多的列表对应的结果越慢
  • 如果列表大多是单调递增的,或者完全随机的,则Michael J.Barbers方法是最快的
以下是试用代码:

import timeit

setup = '''
import random
from itertools import izip, starmap, islice
import operator

def is_increasing_normal(lst):
    for i in range(0, len(lst) - 1):
        if lst[i] >= lst[i + 1]:
            return False
    return True

def is_increasing_zip(lst):
    return all(x < y for x, y in izip(lst, islice(lst, 1, None)))

def is_increasing_sorted(lst):
    return lst == sorted(lst)

def is_increasing_starmap(lst):
    pairs = izip(lst, islice(lst, 1, None))
    return all(starmap(operator.le, pairs))

if {list_method} in (1, 2):
    lst = list(range({n}))
if {list_method} == 2:
    for _ in range(int({n} * 0.0001)):
        lst.insert(random.randrange(0, len(lst)), -random.randrange(1,100))
if {list_method} == 3:
    lst = [int(1000*random.random()) for i in xrange({n})]
'''

n = 100000
iterations = 10000
list_method = 1

timeit.timeit('is_increasing_normal(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)

timeit.timeit('is_increasing_zip(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)

timeit.timeit('is_increasing_sorted(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)

timeit.timeit('is_increasing_starmap(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)
import timeit
设置=“”
随机输入
从itertools导入izip、星图、islice
进口经营者
def正在增加正常值(lst):
对于范围(0,len(lst)-1内的i:
如果lst[i]>=lst[i+1]:
返回错误
返回真值
def正在增加压缩(lst):
返回全部(x
如果列表已经单调递增(
list\u method==1
),则从最快到最慢的是:

  • 分类
  • 星图
  • 正常的
  • 拉链
  • 如果列表基本上是单调递增的(
    list\u method==2
    ),则最快到最慢的是:

  • 星图
  • 拉链
  • 正常的
  • 分类
  • (星图或zip是否最快取决于执行情况,我无法确定模式。星图似乎通常更快)

    如果列表是完全随机的(
    list\u method==3
    ),则最快到最慢的是:

  • 星图
  • 拉链
  • 正常的
  • 分类(非常糟糕)
  • 这个包裹使这很方便

    import pandas as pd
    
    以下命令用于整数或浮点数列表

    (≥): 严格单调递增(>): 使用未记录的私有方法的替代方法:

    pd.Index(mylist)._is_strictly_monotonic_increasing
    
    pd.Index(mylist)._is_strictly_monotonic_decreasing
    
    (≤):
    严格单调递减(这里有一个变量,它同时接受物化序列和非物化序列。它自动确定它是否是
    单调序列,如果是,它的方向(即
    增加
    减少
    )和
    strict
    ness。提供了内联注释以帮助读者。与结尾提供的测试用例类似

        def isMonotonic(seq):
        """
        seq.............: - A Python sequence, materialized or not.
        Returns.........:
           (True,0,True):   - Mono Const, Strict: Seq empty or 1-item.
           (True,0,False):  - Mono Const, Not-Strict: All 2+ Seq items same.
           (True,+1,True):  - Mono Incr, Strict.
           (True,+1,False): - Mono Incr, Not-Strict.
           (True,-1,True):  - Mono Decr, Strict.
           (True,-1,False): - Mono Decr, Not-Strict.
           (False,None,None) - Not Monotonic.
        """    
        items = iter(seq) # Ensure iterator (i.e. that next(...) works).
        prev_value = next(items, None) # Fetch 1st item, or None if empty.
        if prev_value == None: return (True,0,True) # seq was empty.
    
        # ============================================================
        # The next for/loop scans until it finds first value-change.
        # ============================================================
        # Ex: [3,3,3,78,...] --or- [-5,-5,-5,-102,...]
        # ============================================================
        # -- If that 'change-value' represents an Increase or Decrease,
        #    then we know to look for Monotonically Increasing or
        #    Decreasing, respectively.
        # -- If no value-change is found end-to-end (e.g. [3,3,3,...3]),
        #    then it's Monotonically Constant, Non-Strict.
        # -- Finally, if the sequence was exhausted above, which means
        #    it had exactly one-element, then it Monotonically Constant,
        #    Strict.
        # ============================================================
        isSequenceExhausted = True
        curr_value = prev_value
        for item in items:
            isSequenceExhausted = False # Tiny inefficiency.
            if item == prev_value: continue
            curr_value = item
            break
        else:
            return (True,0,True) if isSequenceExhausted else (True,0,False)
        # ============================================================
    
        # ============================================================
        # If we tricked down to here, then none of the above
        # checked-cases applied (i.e. didn't short-circuit and
        # 'return'); so we continue with the final step of
        # iterating through the remaining sequence items to
        # determine Monotonicity, direction and strictness.
        # ============================================================
        strict = True
        if curr_value > prev_value: # Scan for Increasing Monotonicity.
            for item in items:
                if item < curr_value: return (False,None,None)
                if item == curr_value: strict = False # Tiny inefficiency.
                curr_value = item
            return (True,+1,strict)
        else:                       # Scan for Decreasing Monotonicity.
            for item in items: 
                if item > curr_value: return (False,None,None)
                if item == curr_value: strict = False # Tiny inefficiency.
                curr_value = item
            return (True,-1,strict)
        # ============================================================
    
    
    # Test cases ...
    assert isMonotonic([1,2,3,4])     == (True,+1,True)
    assert isMonotonic([4,3,2,1])     == (True,-1,True)
    assert isMonotonic([-1,-2,-3,-4]) == (True,-1,True)
    assert isMonotonic([])            == (True,0,True)
    assert isMonotonic([20])          == (True,0,True)
    assert isMonotonic([-20])         == (True,0,True)
    assert isMonotonic([1,1])         == (True,0,False)
    assert isMonotonic([1,-1])        == (True,-1,True)
    assert isMonotonic([1,-1,-1])     == (True,-1,False)
    assert isMonotonic([1,3,3])       == (True,+1,False)
    assert isMonotonic([1,2,1])       == (False,None,None)
    assert isMonotonic([0,0,0,0])     == (True,0,False)
    
    def isMonotonic(seq):
    """
    seq………:-一个Python序列,具体化与否。
    返回………:
    (True,0,True):-Mono-Const,Strict:Seq-empty或1-item。
    (真、0、假):-单常数,不严格:所有2+序列项相同。
    (正确,+1,正确):-Mono Incr,Strict。
    (真、+1、假):-Mono Incr,不严格。
    (正确,-1,正确):-Mono Decr,Strict。
    (真,-1,假):-Mono Decr,不严格。
    (假,无,无)-不是单调的。
    """    
    items=iter(seq)#确保迭代器(即下一个(…)工作)。
    prev_值=下一个(项目,无)#获取第一个项目,如果为空,则获取无。
    如果prev_value==None:return(True,0,True)#seq为空。
    # ============================================================
    #下一个for/loop扫描,直到找到第一个值更改。
    # ============================================================
    #例:[3,3,
    
    # my solution .. 
    $ python -m timeit "inc = lambda L: reduce(lambda a,b: b if a < b else 9999 , L)!=9999; inc([4,2,3,4,5,6,7,8,7])"
    1000000 loops, best of 3: 1.87 usec per loop
    
    # while the other solution:
    $ python -m timeit "inc = lambda L: all(x<y for x, y in zip(L, L[1:]));inc([4,2,3,4,5,6,7,8,7])"
    100000 loops, best of 3: 2.15 usec per loop
    
    import timeit
    
    setup = '''
    import random
    from itertools import izip, starmap, islice
    import operator
    
    def is_increasing_normal(lst):
        for i in range(0, len(lst) - 1):
            if lst[i] >= lst[i + 1]:
                return False
        return True
    
    def is_increasing_zip(lst):
        return all(x < y for x, y in izip(lst, islice(lst, 1, None)))
    
    def is_increasing_sorted(lst):
        return lst == sorted(lst)
    
    def is_increasing_starmap(lst):
        pairs = izip(lst, islice(lst, 1, None))
        return all(starmap(operator.le, pairs))
    
    if {list_method} in (1, 2):
        lst = list(range({n}))
    if {list_method} == 2:
        for _ in range(int({n} * 0.0001)):
            lst.insert(random.randrange(0, len(lst)), -random.randrange(1,100))
    if {list_method} == 3:
        lst = [int(1000*random.random()) for i in xrange({n})]
    '''
    
    n = 100000
    iterations = 10000
    list_method = 1
    
    timeit.timeit('is_increasing_normal(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)
    
    timeit.timeit('is_increasing_zip(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)
    
    timeit.timeit('is_increasing_sorted(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)
    
    timeit.timeit('is_increasing_starmap(lst)', setup=setup.format(n=n, list_method=list_method), number=iterations)
    
    import pandas as pd
    
    pd.Series(mylist).is_monotonic_increasing
    
    myseries = pd.Series(mylist)
    myseries.is_unique and myseries.is_monotonic_increasing
    
    pd.Index(mylist)._is_strictly_monotonic_increasing
    
    pd.Series(mylist).is_monotonic_decreasing
    
    myseries = pd.Series(mylist)
    myseries.is_unique and myseries.is_monotonic_decreasing
    
    pd.Index(mylist)._is_strictly_monotonic_decreasing
    
        def isMonotonic(seq):
        """
        seq.............: - A Python sequence, materialized or not.
        Returns.........:
           (True,0,True):   - Mono Const, Strict: Seq empty or 1-item.
           (True,0,False):  - Mono Const, Not-Strict: All 2+ Seq items same.
           (True,+1,True):  - Mono Incr, Strict.
           (True,+1,False): - Mono Incr, Not-Strict.
           (True,-1,True):  - Mono Decr, Strict.
           (True,-1,False): - Mono Decr, Not-Strict.
           (False,None,None) - Not Monotonic.
        """    
        items = iter(seq) # Ensure iterator (i.e. that next(...) works).
        prev_value = next(items, None) # Fetch 1st item, or None if empty.
        if prev_value == None: return (True,0,True) # seq was empty.
    
        # ============================================================
        # The next for/loop scans until it finds first value-change.
        # ============================================================
        # Ex: [3,3,3,78,...] --or- [-5,-5,-5,-102,...]
        # ============================================================
        # -- If that 'change-value' represents an Increase or Decrease,
        #    then we know to look for Monotonically Increasing or
        #    Decreasing, respectively.
        # -- If no value-change is found end-to-end (e.g. [3,3,3,...3]),
        #    then it's Monotonically Constant, Non-Strict.
        # -- Finally, if the sequence was exhausted above, which means
        #    it had exactly one-element, then it Monotonically Constant,
        #    Strict.
        # ============================================================
        isSequenceExhausted = True
        curr_value = prev_value
        for item in items:
            isSequenceExhausted = False # Tiny inefficiency.
            if item == prev_value: continue
            curr_value = item
            break
        else:
            return (True,0,True) if isSequenceExhausted else (True,0,False)
        # ============================================================
    
        # ============================================================
        # If we tricked down to here, then none of the above
        # checked-cases applied (i.e. didn't short-circuit and
        # 'return'); so we continue with the final step of
        # iterating through the remaining sequence items to
        # determine Monotonicity, direction and strictness.
        # ============================================================
        strict = True
        if curr_value > prev_value: # Scan for Increasing Monotonicity.
            for item in items:
                if item < curr_value: return (False,None,None)
                if item == curr_value: strict = False # Tiny inefficiency.
                curr_value = item
            return (True,+1,strict)
        else:                       # Scan for Decreasing Monotonicity.
            for item in items: 
                if item > curr_value: return (False,None,None)
                if item == curr_value: strict = False # Tiny inefficiency.
                curr_value = item
            return (True,-1,strict)
        # ============================================================
    
    
    # Test cases ...
    assert isMonotonic([1,2,3,4])     == (True,+1,True)
    assert isMonotonic([4,3,2,1])     == (True,-1,True)
    assert isMonotonic([-1,-2,-3,-4]) == (True,-1,True)
    assert isMonotonic([])            == (True,0,True)
    assert isMonotonic([20])          == (True,0,True)
    assert isMonotonic([-20])         == (True,0,True)
    assert isMonotonic([1,1])         == (True,0,False)
    assert isMonotonic([1,-1])        == (True,-1,True)
    assert isMonotonic([1,-1,-1])     == (True,-1,False)
    assert isMonotonic([1,3,3])       == (True,+1,False)
    assert isMonotonic([1,2,1])       == (False,None,None)
    assert isMonotonic([0,0,0,0])     == (True,0,False)
    
    def IsMonotonic(data):
        ''' Returns true if data is monotonic.'''
        data = np.array(data)
        # Greater-Equal
        if (data[-1] > data[0]):
            return np.all(data[1:] >= data[:-1])
        # Less-Equal
        else:
            return np.all(data[1:] <= data[:-1])
    
    a = [1,2,3,4,5]
    b = [0,1,6,1,0]
    c = [9,8,7,6,5]
    
    def monotonic_increase(x):
        if len(x) <= 1: return False
    
        for i in range(1, len(x)):
            if x[i-1] >= x[i]:
                return False
        return True
    
    def monotonic_decrease(x):
        if len(x) <= 1: return False
    
        for i in range(1, len(x)):
            if x[i-1] <= x[i]:
                return False
    
        return True
    
    monotonic_increase = lambda x: len(x) > 1 and all(x[i-1] < x[i] for i in range(1, len(x)))
    monotonic_decrease = lambda x: len(x) > 1 and all(x[i-1] > x[i] for i in range(1, len(x)))
    
    print(monotonic_increase(a))
    print(monotonic_decrease(c))
    print(monotonic_decrease([]))
    print(monotonic_increase(c))
    print(monotonic_decrease(a))
    print(monotonic_increase(b))
    print(monotonic_decrease(b))