Python проверяет предыдущий элемент больше, чем следующий [дубликат]

Если вы намерены вызвать другие действия из текущей Деятельности, вы должны использовать намерения . Ваш фокус может быть меньше на сохраняющихся данных, чем на совместном использовании его по мере необходимости.

Однако, если вам действительно необходимо сохранить эти значения, вы можете перенести их в какой-то структурированный текстовый файл или базу данных на локальном хранилище. Файл свойств, файл XML или файл JSON могут хранить ваши данные и легко анализироваться во время создания активности. Не забывайте также, что у вас есть SQLite на всех устройствах Android, поэтому вы можете хранить их в таблице базы данных. Вы также можете использовать карту для хранения пар ключ-значение и сериализации карты для локального хранилища, но это может быть слишком громоздким, чтобы быть полезным для простых структур данных.

49
задан Jonathan 17 May 2011 в 07:18
поделиться

10 ответов

def strictly_increasing(L):
    return all(x<y for x, y in zip(L, L[1:]))

def strictly_decreasing(L):
    return all(x>y for x, y in zip(L, L[1:]))

def non_increasing(L):
    return all(x>=y for x, y in zip(L, L[1:]))

def non_decreasing(L):
    return all(x<=y for x, y in zip(L, L[1:]))
112
ответ дан 6502 19 August 2018 в 08:54
поделиться
  • 1
    Это ясный, идиоматический код Python, и его сложность - O (n), где ответы сортировки - все O (n log n). Идеальный ответ будет перебирать список только один раз, чтобы он работал на любом итераторе, но это обычно достаточно хорошо, и это, безусловно, лучший ответ среди тех, которые были до сих пор. (Я бы предложил однопроходное решение, но OP преждевременно принимает ответ, препятствует любому побуждению, которое я, возможно, должен сделать ...) – Glenn Maynard 13 February 2011 в 10:20
  • 2
    просто из любопытства протестировали вашу реализацию против использования отсортированного. У вас явно намного медленнее [я использовал L = диапазон (10000000)]. Кажется, сложность всех - это O (n), и я не мог найти реализацию zip. – Asterisk 13 February 2011 в 10:56
  • 3
    Сортировка является специализированной, если список уже отсортирован. Вы пробовали скорость со случайным перетасованным списком? Также обратите внимание, что с помощью сортировки вы не можете различать строго возрастающее и неубывающее. Также учтите, что с Python 2.x с использованием itertools.izip вместо zip вы можете получить ранний выход (в python 3 zip уже работает как итератор) – 6502 13 February 2011 в 11:17
  • 4
    @ 6502: требуется только одна функция: оператор импорта; def monotone (L, op): вернуть все (op (x, y) для x, y в zip (L, L [1:])), а затем просто передать то, что вы хотите: operator.le или .ge или что-то другое – akira 13 February 2011 в 11:55
  • 5
    zip и оператор slice возвращают целые списки, устраняя возможности ярлыка для всех (); это может быть значительно улучшено за счет использования itertools.izip и itertools.islice, так как либо strict_increasing, либо strict_decreasing должен быстро завершиться с ошибкой. – Hugh Bothwell 13 February 2011 в 16:05

Если у вас есть большие списки чисел, лучше всего использовать numpy, а если вы:

import numpy as np

def monotonic(x):
    dx = np.diff(x)
    return np.all(dx <= 0) or np.all(dx >= 0)

должны сделать трюк.

27
ответ дан Autoplectic 19 August 2018 в 08:54
поделиться
  • 1
    Это, безусловно, лучший ответ! – jb. 2 June 2014 в 21:05
  • 2
    Заметим, что dx [0] np.nan. Вы можете использовать: dx = np.diff (x) [1:], чтобы пропустить его. В противном случае, по крайней мере для меня, вызовы np.all () всегда возвращают False. – Ryan 19 August 2015 в 18:51
  • 3
    @Ryan, почему dx[0] будет NaN? Каков ваш входной массив? – DilithiumMatrix 16 November 2015 в 02:06
  • 4
    N / m, я думал, что np.diff() сделал первый элемент NaN, поэтому форма вывода соответствовала входу, но на самом деле это был другой фрагмент кода, который делал это, что меня било. :) – Ryan 4 December 2015 в 01:00
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:]))
4
ответ дан akira 19 August 2018 в 08:54
поделиться
  • 1
    Я думал о таком решении, но это не удается, если список монотонно возрастает, а первые два элемента равны. – Hugh Bothwell 13 February 2011 в 16:02
  • 2
    @Hugh Bothwell: теперь я проверяю первое и последнее, чтобы получить тренд: если они равны, то все остальные элементы должны быть равны, а затем работают как для operator.le, так и для operator.ge – akira 14 February 2011 в 09:02

Вот функциональное решение, использующее reduce сложности O(n):

is_increasing = lambda L: reduce(lambda a,b: b if a < b else 9999 , L)!=9999

is_decreasing = lambda L: reduce(lambda a,b: b if a > b else -9999 , L)!=-9999

Замените 9999 верхним пределом ваших значений и -9999 с нижним пределом. Например, если вы тестируете список цифр, вы можете использовать 10 и -1.


Я проверил его производительность по сравнению с ответом @ 6502 и его

Случай True: [1,2,3,4,5,6,7,8,9]

# my solution .. 
$ python -m timeit "inc = lambda L: reduce(lambda a,b: b if a < b else 9999 , L)!=9999; inc([1,2,3,4,5,6,7,8,9])"
1000000 loops, best of 3: 1.9 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([1,2,3,4,5,6,7,8,9])"
100000 loops, best of 3: 2.77 usec per loop

Случай False из второго элемента: [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
2
ответ дан Community 19 August 2018 в 08:54
поделиться

@ 6502 имеет идеальный код для списков, я просто хочу добавить общую версию, которая работает для всех последовательностей:

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))
14
ответ дан Jochen Ritzel 19 August 2018 в 08:54
поделиться
  • 1
    +1 для версии, удобной для последовательности – Greg Hewgill 8 May 2012 в 09:33

Я приурочил все ответы в этом вопросе в разных условиях и обнаружил, что:

  • Сортировка была самой быстрой по длинному снимку, если список уже был монотонно возрастающим
  • Сортировка была самой медленной по длинному выстрелу, если список был перетасован / случайным, или если количество элементов не в порядке больше 1. Более того, список курсов соответствует более медленному результату.
  • Метод Майкла Дж. Барберса был самым быстрым, если список был в основном монотонно возрастающим или полностью случайным.

Вот код, чтобы попробовать:

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)

Если список был уже монотонно возрастающим (list_method == 1), самым быстрым для самого медленного был:

  1. sorted
  2. starmap
  3. normal
  4. zip

Если список был в основном монотонно возрастающим (list_method == 2), самым быстрым и медленным было:

  1. starmap
  2. zip
  3. normal
  4. отсортировано

(независимо от того, была ли максимальная скорость starmap или zip зависела от исполнения, и я не мог идентифицировать шаблон. Starmap, казалось, обычно быстрее)

Если список был полностью случайным (list_method == 3), , самый быстрый до самого медленного был:

  1. starmap
  2. zip
  3. normal
  4. отсортировано (очень плохо)
1
ответ дан Matthew Moisen 19 August 2018 в 08:54
поделиться
  • 1
    Я не пробовал метод @Assem Chelli, так как он требовал знания максимального элемента в списке – Matthew Moisen 14 November 2016 в 05:22
  • 2
    Какие решения будут работать при передаче генератора? – PaulMcG 26 September 2017 в 12:37
import itertools
import operator

def monotone_increasing(lst):
    pairs = zip(lst, lst[1:])
    return all(itertools.starmap(operator.le, pairs))

def monotone_decreasing(lst):
    pairs = zip(lst, lst[1:])
    return all(itertools.starmap(operator.ge, pairs))

def monotone(lst):
    return monotone_increasing(lst) or monotone_decreasing(lst)

Этот подход равен O(N) в длине списка.

24
ответ дан Michael J. Barber 19 August 2018 в 08:54
поделиться
  • 1
    Правильное (TM) решение IMO. Функциональная парадигма для победы! – progo 13 February 2011 в 10:00
  • 2
    Я бы сказал, что он меняет читаемость на ум. – Zack Bloom 13 February 2011 в 10:04
  • 3
    зачем использовать itertools вместо простых генераторов? – 6502 13 February 2011 в 10:14
  • 4
    Функциональные парадигмы обычно не являются «выигрышем». в Python. – Glenn Maynard 13 February 2011 в 10:15
  • 5
    Вычисление пар также O(N). Вы можете сделать pairs = itertools.izip(lst, itertools.islice(lst, 1, None)). – Tomasz Elendt 13 February 2011 в 10:36
>>> l = [0,1,2,3,3,4]
>>> l == sorted(l) or l == sorted(l,reverse=True)
-2
ответ дан Senthil Kumaran 19 August 2018 в 08:54
поделиться
L = [1,2,3]
L == sorted(L)

L == sorted(L, reverse=True)
0
ответ дан Zack Bloom 19 August 2018 в 08:54
поделиться
  • 1
    Я бы пошел за sorted(), если бы он ничего не сортировал, просто проверьте. Плохо названный - звучит как предикат, когда это не так. – progo 13 February 2011 в 10:07
  • 2
  • 3
    Это алгоритмически плохое; это решение O (n log n), когда эту задачу можно сделать тривиально в O (n). – Glenn Maynard 13 February 2011 в 10:14
  • 4
    @ Все согласны со всеми вами, спасибо за конструктивную критику. – Asterisk 13 February 2011 в 10:21
  • 5
    Я протестировал все решения в этом потоке здесь и обнаружил, что отсортированный метод на самом деле является лучшим ... если список на самом деле монотонно возрастает. Если в списке есть какие-либо предметы, они становятся самыми медленными. – Matthew Moisen 14 November 2016 в 05:25
0
ответ дан A-B-B 30 October 2018 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: