Правильно организовать (распределить) данные x и y

Не совсем уверен, как сформулировать этот вопрос, поэтому я приведу пример того, что я хочу.

У меня есть две переменные xsteps и ysteps.

Если xsteps равно 4, а ysteps равно 2, то я хотел бы, чтобы результат переменной был "x, x, y, x, x, y"
Если xsteps равен 10, а ysteps равен 5, то я хотел бы, чтобы результат был "x, x, y, x, x, y, x, x, y, x, x, y, x, x, y"
Если xsteps равно 15, а ysteps равно 5, то я бы хотел, чтобы результат был " x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y, x, x, x, y"
Если xsteps равно 1, а ysteps равно 6, я хотел бы, чтобы результат был "x, y, y, y, y, y, y"
Если xsteps равно 4 и ysteps равно 4, я хотел бы, чтобы результат был "x, y, x, y, x, y, x, y"
Если xsteps равно 10, а ysteps равно 4, я хотел бы, чтобы результат был "x, x, y, x, x, y, x, x, y, x, x, y , х, х"

Шаги X и шаги y не всегда легко разделить. Если они не делятся, то я просто хотел бы, чтобы они были как бы отделены друг от друга. Он не должен быть идеальным, просто он распределяет их достаточно хорошо.

Действительно, мне нужны переменные xsteps и ysteps, организованные в одну переменную, которая их распределяет.


person user2370460    schedule 29.04.2014    source источник
comment
Всегда ли одно является делителем другого?   -  person tobias_k    schedule 29.04.2014
comment
Я не понимаю, что вы имеете в виду. Запишите алгоритм и покажите нам, что вы пробовали. Вы отметили вопрос с помощью Python, но не показали нам фрагмент кода.   -  person freakish    schedule 29.04.2014
comment
@tobias_k нет, не обязательно   -  person user2370460    schedule 29.04.2014
comment
Затем покажите пример, когда это не так.   -  person tobias_k    schedule 29.04.2014
comment
@freakish, это потому, что я не знаю, с чего начать, и надеюсь, что кто-то может мне помочь. Он помечен как python, потому что я хотел бы, чтобы он был написан на python.   -  person user2370460    schedule 29.04.2014
comment
Это, вероятно, излишне для этой проблемы, но здесь связанный с этим вопрос.   -  person tobias_k    schedule 29.04.2014


Ответы (4)


Вы можете попробовать что-то вроде этого:

from __future__ import division
def spreadout(X, Y):
    ratio = len(X) / len(Y)
    result = []
    while X or Y:
        if not Y or len(X)/len(Y) >= ratio:
            result.append(X.pop())
        else:
            result.append(Y.pop())
    return result

Идея алгоритма состоит в том, чтобы определить соотношение списков X и Y и поочередно pop элементов из любого из списков, чтобы соотношение в списке result оставалось одинаковым.

Эта реализация работает со списками произвольных элементов и возвращает результат в виде списка. Если вам нужна только ваша строка x,y, код можно упростить и оптимизировать, например. использование len часто было бы расточительным, если у вас очень длинные списки x и y. Или вы можете просто написать оболочку для этого:

def xy_wrapper(x, y):
    return ",".join(spreadout(['x'] * x, ['y'] * y))

Пример вывода:

>>> spreadout(range(6), list("ABC"))
[5, 'C', 4, 3, 'B', 2, 1, 'A', 0]
>>> xy_wrapper(5, 17)
'x,y,y,y,y,x,y,y,y,x,y,y,y,y,x,y,y,y,x,y,y,y'
person tobias_k    schedule 29.04.2014
comment
+1 Хорошее решение - похоже на мое, но я думаю, что мое должно иметь лучшую производительность, так как я не создаю промежуточные списки - пожалуйста, посмотрите и оцените меня :) - person ElmoVanKielmo; 30.04.2014
comment
@ElmoVanKielmo Мое решение, конечно, не самое быстрое, но опять же, оно немного более универсальное. Фактически, ваше решение на 99% похоже на то, что было у меня сначала (тогда я его не публиковал), прежде чем решил сделать его более общим. Однако ловкий трюк, позволяющий избежать деления на ноль. - person tobias_k; 30.04.2014

def spread_generator(xsteps, ysteps):
    ratio = xsteps / ysteps
    while xsteps > 0 or ysteps > 0:
        if xsteps > ratio * ysteps:
            yield "x"
            xsteps -= 1
        else:
            yield "y"
            ysteps -= 1

xsteps = 7
ysteps = 3
result = [x for x in spread_generator(xsteps, ysteps)]
# Next line will make result variable hold desired value
result.reverse()
print result
# ['x', 'x', 'y', 'x', 'x', 'y', 'x', 'x', 'y', 'x'] 
# And if you want string
result_as_str = ",".join(result)
print result_as_str
# x,x,y,x,x,y,x,x,y,x

Решающим значением является ratio между x и y шагами.
В начале список перевернут, поэтому мы его переворачиваем.
Помните, что list.reverse() изменяет список на месте и возвращает None.

person ElmoVanKielmo    schedule 29.04.2014

Похоже, кто-то опередил меня, написав гораздо более приятный ответ, но я написал его сейчас!

Это было бы близко к тому, что вы хотите, но ваш пример для (10, 4) не работает так, как вы его указали.

def xy_spread(xsteps, ysteps):
    out = []

    if xsteps == 0:
        out = ['y'] * ysteps    
    else:
        y_per_x = float(ysteps) / float(xsteps)
        y_budget = 0.0

        for _ in xrange(xsteps):
            out.append('x')
            y_budget += y_per_x

            while y_budget >= 1:
                y_budget -= 1
                out.append('y')

    return ','.join(out)
person Jon Betts    schedule 29.04.2014

Не обязательно красиво, но функционально. По сути, кажется, что вы хотите разделить xsteps на куски и вставить «y» между кусками, пока не закончатся x или y.

def get_chunks(mylist, n):
    """
    Adapted from:
    http://www.how2code.co.uk/2013/04/how-to-split-a-list-into-chunks-in-python/
    """
    if n == 0:
        return mylist
    else:
        return [mylist[x:x+n] for x in range(0, len(mylist), n)]

def combine(xs=0, ys=0):
    """
    >>> combine(xs=4, ys=2)
    x,x,y,x,x,y
    >>> combine(xs=10, ys=5)
    x,x,y,x,x,y,x,x,y,x,x,y,x,x,y
    >>> combine(xs=15, ys=5)
    x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y,x,x,x,y
    >>> combine(xs=1, ys=6)
    x,y,y,y,y,y,y
    >>> combine(xs=4, ys=4)
    x,y,x,y,x,y,x,y
    >>> combine(xs=10, ys=4)
    x,x,y,x,x,y,x,x,y,x,x,y,x,x
    """
    output = list()
    x = ['x'] * xs
    y = ['y'] * ys
    step = xs // ys
    xchunks = get_chunks(x, step)

    while xchunks or y:
        if xchunks:
            output += xchunks.pop()
        if y:
            output += y.pop()

    print ','.join(output)
person Nick    schedule 29.04.2014