简体   繁体   English

在字符串中连续添加数字

[英]Consecutive addition of numbers in a string

I'm a new programmer learning python and am having trouble with how to approach this task: 我是一个学习python的新程序员,我遇到了如何处理这个任务的麻烦:

So essentially I have a string of numbers to read imported from a file, and need to add the sum of the first number to the second and convert it to the correct ascii character. 所以基本上我有一串数字要读取从文件导入,并需要将第一个数字的总和添加到第二个数字并将其转换为正确的ascii字符。 So, for example if I am reading the string: 所以,例如,如果我正在读取字符串:

'36 30 25 40 80 4' 

I would want to add 36 to 30, then 25 to 40, then 80 to 4 and so on, before converting them to the corresponding ASCII character and printing (so in this case 'CAT'). 我想在将它们转换为相应的ASCII字符并打印之前添加36到30,然后是25到40,然后是80到4,依此类推,因此在本例中为“CAT”。

So far i recognize that i need to use a split command to split the string, and then a for loop to take the data for consecutive numbers. 到目前为止,我认识到我需要使用split命令来拆分字符串,然后使用for循环来获取连续数字的数据。 I can get the correct value for the first letter, but am having trouble 'telling' the program to atuomatically move on to add [2] to [3] after adding [1] to [0]. 我可以得到第一个字母的正确值,但是在将[1]添加到[0]之后,我很难“告诉”程序在[...]上添加[2]到[3]。 I also need to do this for multiple lines. 我还需要为多行做这个。

Again, I'm a new coder so any help is greatly appreciated. 再一次,我是一个新的编码器,所以任何帮助都非常感谢。 Thanks! 谢谢!

You can use a special usage of zip to pair up elements: 您可以使用zip的特殊用法来配置元素:

s = '36 30 25 40 80 4'
ints = map(int, s.split()) #make into list of ints
sums = map(sum, zip(*[iter(ints)]*2))
print(''.join([chr(i) for i in sums]))

Edit: technically the iter is unnecessary here, but I write it because I sometimes forget when I do need it. 编辑:从技术上讲,这里不需要iter ,但我写它是因为我有时会忘记它需要它。

Edit 2: addressing jsbuenos points below: 编辑2:解决以下jsbuenos点:

map takes a function and an iterable (like a list) and applies the function to every element of that iterable. map接受一个函数和一个iterable(如列表),并将该函数应用于该iterable的每个元素。 So list(map(int, ['1', '2'])) is the same as [int('1'), int('2')] . 所以list(map(int, ['1', '2']))[int('1'), int('2')] The list is there because map actually returns an iterator that produces the values one at a time instead of all at once. list就在那里,因为map实际上返回一个迭代器,它一次生成一个值而不是一次生成所有值。

The usage of zip here looks complex, but that's mostly all the punctuation. 这里使用zip看起来很复杂,但这主要是所有的标点符号。 Let's try and break it down. 让我们试着把它分解。 As I mentioned, we don't need the iter here because ints is a map object, and thus already an iterator, so we don't have to make an iterator for it. 正如我所说,我们并不需要的iter在这里,因为ints是一个map对象,因此已经是一个迭代器,所以我们没有做一个迭代器了。 So now it looks like 所以现在看起来像

sums = map(sum, zip(*[ints]*2))

All the map is doing is adding up the pairs after we pair them up, so let's discard that too. 所有map正在做的是在我们配对之后加起来,所以我们也放弃它。

zip(*[ints]*2)

The trick to understanding this is understanding that list multiplication happens first 理解这一点的诀窍是理解列表乘法首先发生

zip(*[ints, ints])

The * in front of an iterable is the unpacking operator. 迭代前面的*是解包操作符。 Think of it as the list dumping its arguments into the function 可以将其视为将其参数转储到函数中的列表

zip(ints, ints)

So what is zip actually doing? zip实际上是做什么的? The normal usage of zip is to take two iterables and pair the elements up, like so. zip的正常用法是采用两个迭代并将元素配对,就像这样。

list(zip([1,2,3], [4,5,6])) #put the results from zip into a list
[(1, 4), (2, 5), (3, 6)]

It works with more than two lists too, but that's not what we're here for. 它也适用于两个以上的列表,但这不是我们在这里的目的。

It's important to note that in zip(ints, ints) the two ints arguments are the same object. 重要的是要注意,在zip(ints, ints) ,两个ints参数是同一个对象。 This means that when zip makes the first pair, it first gets the next element from its first argument, ints . 这意味着当zip创建第一对时,它首先从第一个参数ints获取下一个元素。 That's 36 . 那是36 Then it gets the next element from its second argument which is the same ints . 然后它从第二个参数得到下一个元素,它是相同的ints So the next element is 30 . 所以下一个元素是30 It then yields those two elements in a tuple, and goes on to repeat the process for the rest of the iterator. 然后它在元组中产生这两个元素,然后继续为迭代器的其余部分重复该过程。

If you're asking yourself "Why write zip(*[iter(ints)]*2) when zip(ints, ints) means the same thing?" 如果你问自己“为什么写zip(*[iter(ints)]*2)zip(ints, ints)意味着同样的事情?” it's because you have to make sure that the arguments are the same object, or it doesn't work. 这是因为你必须确保参数是同一个对象,否则它不起作用。 Doing zip(iter(ints),iter(ints)) wouldn't work because each iter returns a different, though identical, iterator. 执行zip(iter(ints),iter(ints))是行不通的,因为每个iter返回一个不同但相同的迭代器。 I have trouble remembering when I have to use iter , so to play it safe I just use it all the time. 我不记得,当我不得不使用iter ,所以为了安全起见我只是用它所有的时间。

Another method that is less opaque (though more verbose) than Patrick's proposal would be: 另一种比帕特里克提议更不透明(虽然更冗长)的方法是:

>>> x = '36 30 25 40 80 4'
>>> nums = [int(n) for n in x.split()]
>>> ''.join(chr(sum(nums[i:i+2])) for i in range(0, len(nums), 2))
'BAT'

If this is ascii encoding, I think you actually have 'BAT' instead of 'CAT'. 如果这是ascii编码,我认为你实际上有'BAT'而不是'CAT'。

>>> s = '36 30 25 40 80 4'
>>> ints = [int(n) for n in s.split()]             # convert strings to integers
>>> summed = [x+y for x,y in zip(ints[0::2], ints[1::2])]        # summing pairs
>>> bytearray(summed).decode('ascii')                   # decoding to ascii text
'BAT'

You can do it with a no brainer like this: 你可以这样做,没有脑子:

In [18]: str='36 30 25 40 80 4'

In [19]: nums=str.split()

In [20]: for i in range(0, len(nums), 2):
    print(int(nums[i]) + int(nums[i+1]))
   ....:     
66
65
84

Possibly you want to check, that the len(nums) is even. 可能你想检查,len(nums)是偶数。 If not an IndexError will be thrown. 如果不是,则抛出IndexError。

You may do it using list comprehesnion as: 你可以使用list comprehesnion来做到:

>>> my_string = '36 30 25 40 80 4'
>>> num_list = [int(num) for num in my_string.split()] # list of numbers
>>> ''.join(chr(sum(c_num)) for c_num in zip(num_list[:-1:2], num_list[1::2]))
'BAT'     #                                    ^ iterate simultaneous value with step 2

You can use for loop with range with step 2 您可以在步骤2中使用带范围的循环

    for i in range(0, 6, 2):
        do something to el[i] and el[i+1]

This way you can tell program to go to wanted index. 这样你就可以告诉程序去想要的索引。 Here i in loop will get values: [0, 2, 4] 我在循环中将得到值:[0,2,4]

Another solution: 另一种方案:

string = '36 30 25 40 80 4'
numbers = [int(e) for e in string.split()]
res = ''.join([chr(numbers[i]+numbers[i+1]) for i in range(0,len(numbers),2)])
print(res)

Output: BAT 输出: BAT

A slight alteration from Patricks answer. 帕特里克回答略有改动。

>>> t = "36 30 25 40 80 4"
>>> t_s = map(int,t.split())
>>> t_s
[36, 30, 25, 40, 80, 4]
>>> "".join([chr(sum(c)) for c in zip(t_s[1::2],t_s[::2])])
'BAT'

you can use extended list slicing to get pairs of adjacent numbers: 您可以使用扩展列表切片来获取相邻数字对:

s = '36 30 25 40 80 4'
a = [int(x) for x in s.split()] #convert to integers
firsthalf = a[::2] #every other starting from 0
secondhalf = a[1::2] #every other starting from 1

Then you can use zip to pair the halves to be summed: 然后你可以用zip来配对要求的两半:

pairs = zip(firsthalf, secondhalf)

then you can map sum on each part of paris: 然后你可以在巴黎的每个部分上绘制sum

ordinals = [sum(x) for x in pairs]

to finally convert to a string, call: 最后转换为字符串,调用:

print(''.join([chr(x) for x in ordinals])) #prints: 'BAT'

Many way to do this but without creating a number of intermediate lists you can simply create an iterator and use a generator to construct the string: 很多方法可以做到这一点但是没有创建许多中间列表,你可以简单地创建一个迭代器并使用生成器来构造字符串:

>>> s = '36 30 25 40 80 4'
>>> i = iter(map(int, s.split()))
>>> ''.join(chr(sum(x)) for x in zip(i, i))
'BAT'

You can convert the string to the iterator returning ints, and use next function inside a list comprehension: 您可以将字符串转换为返回int的迭代器,并在列表解析中使用next函数:

s = '36 30 25 40 80 4' 

# iter is not necessary in python3
itr = iter(map(int, s.split()))
word = ''.join(chr(a+next(itr)) for a in itr)

print(word)
# BAT

IMO this is a bit cleaner because there is no explicit indexing. IMO这个有点清洁,因为没有明确的索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM