Лучший способ разделить список целых чисел на основе значений и правил - PullRequest
1 голос
/ 23 апреля 2019

Цель состоит в том, чтобы разбить список целых чисел на основе соседей каждого элемента на основе следующих правил:

  • (текущее / фокусное значение меньше или равно предыдущему)и (текущее значение равно следующему), то есть prev_value >= focal_value == next_value

  • (текущее значение меньше предыдущего) и (текущее значение меньше следующего),то есть prev_value > focal_value < next_value

Для иллюстрации, учитывая, что x производят y:

x = (1, 4, 2, 1, 4, 2, 4, 1, 4, 1, 4, 4, 3)
y = [[1, 4, 2], [1, 4], [2, 4], [1, 4], [1, 4, 4, 3]]
assert func(x) == y

Я пробовал:

def per_window(sequence, n=1):
    """
    From http://stackoverflow.com/q/42220614/610569
        >>> list(per_window([1,2,3,4], n=2))
        [(1, 2), (2, 3), (3, 4)]
        >>> list(per_window([1,2,3,4], n=3))
        [(1, 2, 3), (2, 3, 4)]
    """
    start, stop = 0, n
    seq = list(sequence)
    while stop <= len(seq):
        yield tuple(seq[start:stop])
        start += 1
        stop += 1


def func(x):
    result = []
    sub_result = [x[0]]
    for prev_value, focal_value, next_value in per_window(x, 3):
        # These if and elif cases trigger syllable break.
        if prev_value >= focal_value == next_value:
            sub_result.append(focal_value)
            result.append(sub_result)
            sub_result = []
        elif prev_value > focal_value < next_value:
            result.append(sub_result)
            sub_result = []
            sub_result.append(focal_value)
        else: # no  break
            sub_result.append(focal_value)
    sub_result.append(next_value)
    result.append(sub_result)
    return result


x = (1, 4, 2, 1, 4, 2, 4, 1, 4, 1, 4, 4, 3)
y = [[1, 4, 2], [1, 4], [2, 4], [1, 4], [1, 4, 4, 3]]

assert func(x) == y

Но мои вопросы таковы:

  • Если мы внимательно рассмотрим «дела» if и elif, то это будет похоже на первое, если никогда не будет захвачено, так как второе прибудет первым,Это правильно?В каких примерах будут запущены первые if дел?

  • Есть ли лучший способ достичь той же цели разделения списка на основе правил?

  • Последние два добавления должны существовать вне цикла per_window, как зовут эти душители?Есть ли способ зацикливаться без этого?

1 Ответ

1 голос
/ 23 апреля 2019
  1. В вашем примере первый if никогда не срабатывает.Но это будет с данными этого примера:

    x = (5 ,4, 4, 2)
    y = [[5, 4], [4, 2]]
    
  2. Лучше, скорее, субъективно.Но можно достичь той же цели без использования окон, просто сдвигая значения

    def func2(x):
        x = iter(x)
        try:
            prev_value = next(x)
            focal_value = next(x)
        except StopIteration:
            return [list(x)]
        sub_result = [prev_value]
        result = [sub_result]
        for next_value in x:
            if prev_value >= focal_value == next_value:
                sub_result.append(focal_value)
                sub_result = []
                result.append(sub_result)
            elif prev_value > focal_value < next_value:
                sub_result = [focal_value]
                result.append(sub_result)
            else:
                sub_result.append(focal_value)
            prev_value, focal_value = focal_value, next_value
        sub_result.append(focal_value)
        return result
    

    timeit говорит, что это более чем в два раза быстрее

  3. Каккак только вы удерживаете последнее значение в цикле, вам нужно будет добавить специальную обработку для него после цикла.Но мой код показывает, что можно добавить список sub_result внутри цикла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...