首页 > 解决方案 > 如何根据总字符将 Discord 字段拆分为 x 次?

问题描述

我一直在尝试如何在Discord中拆分字段,其中每个字段的字符限制为 1024 个字符。

我的问题是,当字符介于 900-2000 个字符之间时,我只能拆分为两个列表,但是我确实得到了字符(我将在代码中显示的 listInfo)总共超过 2000 个字符。

我想弄清楚的是我如何能够将嵌入的字段拆分为 x 次,其中 0-900 是一个字段,900-1800 是第二个字段,1800-2700 是第三个字段等等。(每个字段都是 n + 900)。

data = []

listInfo = [
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167764|EU 40 - [2]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167765|EU 40.5 - [4]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167766|EU 41 - [4]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167767|EU 42 - [4]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167768|EU 42.5 - [8]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167769|EU 43 - [9]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167770|EU 44 - [14]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167771|EU 44.5 - [8]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167772|EU 45 - [16]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167773|EU 45.5 - [8]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167774|EU 46 - [16]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167775|EU 47 - [5]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167776|EU 47.5 - [4]>',
  '<https://www.justrandomlink.com/?controller=cart&add=1&as=true&qty=1&id_product=20798&token=e4d64f25476dcee4b08744d382dc405b&ipa=167777|EU 48.5 - [4]>'
]


if 900 <= sum(len(i) for i in listInfo) < 2000:

    data.append(
        {
            'title': 'Info',
            'value': '\n'.join(listInfo[:len(listInfo)//2]) if len(listInfo) else '*Info not found*',
            'short': True
        }
    )

    data.append(
        {
            'title': '-',
            'value': '\n'.join(listInfo[len(listInfo)//2:]) if len(listInfo) else '*Info not found*',
            'short': True
        }
    )

elif 0 < sum(len(i) for i in listInfo) < 900:
    data.append(
        {
            'title': 'Info',
            'value': '\n'.join(listInfo) if len(listInfo) else '*Info not found*',
            'short': False
        }
    )

我试图找出一种更聪明的方法,即我不添加另一个在 3 上拆分然后再拆分为 4 等的函数。

标签: pythonjoinsplitdiscord

解决方案


处理此问题的一种方法是保持当前批次大小的运行总计,并使用该总计来确定是添加到当前批次还是创建新批次。

data, character_count, i = [], 0, 0
for j, item in enumerate(listInfo):
    if len(item) + character_count > 900:
        data.append('\n'.join(listInfo[i:j]))
        character_count, i = len(item), j
    else:
        character_count += len(item)
if character_count:
    data.append('\n'.join(listInfo[i:]))
if not data:
    data.append('*Info not found*')

如果您可以采取几个步骤,而不是使用enumerate来跟踪您在列表中的位置并.join在枚举中使用,那么只需批处理任何新行并担心以后加入它们是可行的。

data, character_count = [], 0
for item in listInfo:
    if len(item) + character_count > 900:
        data.append([item])
        character_count = len(item)
    else:
        data[-1].append(item)
        character_count += len(item)
data = ['\n'.join(batch) for batch in data]
if not data:
    data.append('*Info not found*')

这样做的一个问题是它占用了大量的内存空间。您可以使用称为生成器的东西继续提供每个批次,而不是附加到列表中。如果调用生成器的人出于某种原因实际上需要一个列表,他们可以从生成器中创建一个列表,否则他们可以只处理流中的项目。

def batch(listInfo):
    batch, count = [], 0
    for item in listInfo:
        if len(item) + count > 900:
            yield batch
            batch, count = [item], len(item)
        else:
            batch.append(item)
            count += len(item)
    if batch:
        yield batch
data = ['\n'.join(x) for x in batch(listInfo)]
if not data:
    data.append('*Info not found*')

在某种程度上,仍然存在您是否想要正好900 个字符的消息(可能拆分传入消息)或是否要保持消息完整的问题。保持消息完整且仅在消息之间拆分的一个问题是,您的列表项之一可能单独超过 900 个字符。我编写的所有代码都隐含地假设情况并非如此,因为您希望消息包装、不发送或在这种情况下以其他方式表现的确切方式实际上取决于应用程序。


推荐阅读