需要以循环顺序获取一组数字

2024-06-25 23:26:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一些python脚本来生成JSON。我成功构建了jSON。但在循环顺序中选择数字的过程中陷入了困境。 让我们说,我有一个1,2,3,4,5的列表。我需要在这里选择前4个数字(1,2,3,4)作为第一项,选择2,3,4,5作为第二项,选择3,4,5,1作为第三项,应该持续到30次。你知道吗

import json
import random
json_dict = {}
number = []
brokers = [1,2,3,4,5]

json_dict["version"] = version
json_dict["partitions"] = [{"topic": "topic1", "name": i,"replicas": 
random.choice(brokers)} for i in range(0, 30)]

with open("output.json", "w") as outfile:
    json.dump(json_dict, outfile, indent=4) 

输出

"version": "1", 
"partitions": [
    {
        "topic": "topic1", 
        "name": 0, 
        "replicas": 1,2,3,4
    }, 
    {
        "topic": "topic1", 
        "name": 1, 
        "replicas": 2,3,4,5
    }, 
    {
        "topic": "topic1", 
        "name": 3, 
        "replicas": 3,4,5,1

不管怎样,我怎样才能做到这一点?你知道吗


Tags: nameimport脚本jsontopicversion数字random
3条回答

为了从brokers list中获得循环元素,您可以使用collections模块中的deque并执行deque.rotation(-1)如下示例:

from collections import deque

def grouper(iterable, elements, rotations):
    if elements > len(iterable):
        return []

    b = deque(iterable)
    for _ in range(rotations):
        yield list(b)[:elements]
        b.rotate(-1)

brokers = [1,2,3,4,5]
# Pick 4 elements from brokers and yield 30 cycles
cycle = list(grouper(brokers, 4, 30))
print(cycle)

输出:

[[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5,1, 2], [5, 1, 2, 3]]

此外,这也是如何将此解决方案实施到最终dict的一种方法:

# in this example i'm using only 5 cycles
cycles = grouper(brokers, 4, 5)
partitions = [{"topic": "topic1", "name": i, "replicas": cycle_elem} for i, cycle_elem in zip(range(5), cycles)]
final_dict = {"version": "1", "partitions": partitions}

print(final_dict)

输出:

{'partitions': [{'name': 0, 'replicas': [1, 2, 3, 4], 'topic': 'topic1'}, {'name': 1, 'replicas': [2, 3, 4, 5], 'topic': 'topic1'}, {'name': 2, 'replicas': [3, 4, 5, 1], 'topic': 'topic1'}, {'name': 3, 'replicas': [4, 5, 1, 2], 'topic': 'topic1'}, {'name': 4, 'replicas': [5, 1, 2, 3], 'topic': 'topic1'}], 'version': '1'}

这是一个纯粹的程序性解决方案,它还增加了选择任意数量、任意规模(甚至比原来的“经纪人”名单还要大)的组的灵活性,并提供了任何补偿:

def get_subgroups(groups, base, size, offset=1):
    # cover the group size > len(base) case by expanding the base
    # this step is completely optional if your group size will never be bigger
    base *= -(-size // len(base))

    result = []  # storage for our groups
    base_size = len(base)  # no need to call len() all the time
    current_offset = 0  # tracking current cycle offset
    for i in range(groups):  # use xrange() on Python 2.x instead
        tail = current_offset + size  # end index for our current slice
        end = min(tail, base_size)  # normalize to the base size
        group = base[current_offset:end] + base[:tail - end]  # get our slice
        result.append(group)  # append it to our result storage
        current_offset = (current_offset + offset) % base_size  # increase our current offset
    return result

brokers = [1, 2, 3, 4, 5]

print(get_subgroups(5, brokers, 4))  # 5 groups of size 4, with default offset
# prints: [[1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 1], [4, 5, 1, 2], [5, 1, 2, 3]]

print(get_subgroups(3, brokers, 7, 2))  # 3 groups of size 7, with offset 2
# prints: [[1, 2, 3, 4, 5, 1, 2], [3, 4, 5, 1, 2, 3, 4], [5, 1, 2, 3, 4, 5, 1]]

它用一个循环在一个O(N)时间内完成。你知道吗

如果您计划在一个非常大的生成器上运行这个函数,您可以通过放弃result集合并执行yield group而不是result.append(group)来将get_subgroups()函数转换为生成器。这样,您就可以在循环中调用它:for group in get_subgroups(30, broker, 4):,并将group存储在您想要的任何结构中。你知道吗

更新

如果内存不是一个问题,我们可以通过扩展整个base(或者在您的情况下是brokers)以适应整个集合来进一步优化(处理方面):

def get_subgroups(groups, base, size, offset=1):  # warning, heavy memory usage!
    base *= -(-(offset * groups + size) // len(base))
    result = []  # storage for our groups
    current_offset = 0  # tracking current cycle offset
    for i in range(groups):  # use xrange() on Python 2.x instead
        result.append(base[current_offset:current_offset+size])
        current_offset += offset
    return result

或者,如果我们不需要将列表转换为生成器的能力,我们可以通过列表理解使其更快:

def get_subgroups(groups, base, size, offset=1):  # warning, heavy memory usage!
    base *= -(-(offset * groups + size) // len(base))
    return [base[i:i+size] for i in range(0, groups * offset, offset)]
    # as previously mentioned, use xrange() on Python 2.x instead

这是一个很酷的问题,我想我有一个很酷的解决方案:

items = [1, 2, 3, 4, 5]
[(items * 2)[x:x+4] for i in range(30) for x in [i % len(items)]]

这给了

[[1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3],
 [1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3],
 [1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3],
 [1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3],
 [1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3],
 [1, 2, 3, 4],
 [2, 3, 4, 5],
 [3, 4, 5, 1],
 [4, 5, 1, 2],
 [5, 1, 2, 3]]

它所做的是将你的一组东西附加到它本身(items * 2->;[1, 2, 3, 4, 5, 1, 2, 3 ,4, 5]),然后选择一个开始的地方(x),通过循环迭代(i)并根据我们拥有的项数(i in [x % len(items)])调整它(可能不是正确的词)。你知道吗

相关问题 更多 >