Reputation: 629
I have been trying out a way how to split fields in Discord where each field has a character limitation of 1024 characters.
My problem is that I have only been able to split into two lists whenever the character is between 900-2000 characters however it does happend that I do get characters (listInfo which I will show in code) is above 2000 character total.
What I am trying to figure out is that how I am able to split the Field embed into x times where 0-900 is one field, 900-1800 is second field, 1800-2700 is third field etc etc. (Each field is 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
}
)
I am trying to figure out a smarter way where I dont add another function that is split on 3 and then for 4 etc etc.
Upvotes: 0
Views: 129
Reputation: 7141
One way to handle this is to keep a running total of the current batch size and use that total to determine whether to add to the current batch or to make a new batch.
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*')
If you're fine with this taking a couple steps, rather than using enumerate
to keep track of where you are in the list and using .join
inside the enumeration, it's feasible to just batch any new lines and worry about joining them later.
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*')
One problem with this is that it takes a lot of space in memory. Rather than appending to a list you can use something called a generator to continue providing each batch. If the person calling the generator actually needs a list for some reason they can make one from the generator, but otherwise they can just process the items in a stream.
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*')
At some level, there's still the question of whether you want messages that are exactly 900 characters (perhaps splitting the incoming messages) or whether you want to keep messages intact. One problem with keeping messages intact and only splitting between messages is that one of your list items can be greater than 900 characters all by itself. All the code I've written implicitly assumes that to not be the case since the exact way you want messages to wrap, not be sent, or otherwise behave in that case is really application dependant.
Upvotes: 2