我是一名学习python的新程序员,我在如何处理这项任务时遇到了麻烦:
所以基本上我有一串数字要读取从文件中导入,并且需要将第一个数字的总和添加到第二个数字并将其转换为正确的ascii字符。所以,例如,如果我正在读取字符串:
'36 30 25 40 80 4'
我希望在将它们转换为相应的ASCII字符并打印之前添加36到30,然后是25到40,然后是80到4,依此类推。(在这种情况下,“CAT”)。
到目前为止,我认识到我需要使用split命令来拆分字符串,然后使用for循环来获取连续数字的数据。我可以得到第一个字母的正确值,但是在将[1]添加到[0]之后,我很难“告诉”程序在[...]上添加[2]到[3]。我还需要为多行做这个。
同样,我是一个新的编码器,所以任何帮助都非常感谢。谢谢!
答案 0 :(得分:3)
您可以使用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]))
编辑:从技术上来说,iter
在这里是不必要的,但是我写这篇文章是因为我有时会在需要时忘记它。
编辑2:解决下面的jsbuenos点:
map
接受一个函数和一个iterable(如列表),并将该函数应用于该iterable的每个元素。因此list(map(int, ['1', '2']))
与[int('1'), int('2')]
相同。 list
就在那里,因为map
实际上返回一个迭代器,它一次生成一个值,而不是一次生成所有值。
zip
的用法看起来很复杂,但这主要是标点符号。让我们尝试将其分解。正如我所提到的,我们不需要iter
,因为ints
是map
对象,因此已经是迭代器,所以我们不必做它的迭代器。所以现在它看起来像
sums = map(sum, zip(*[ints]*2))
所有map
正在做的就是在我们配对之后将它们相加,所以我们也放弃它们。
zip(*[ints]*2)
理解这一点的诀窍是理解列表乘法首先发生
zip(*[ints, ints])
可迭代前面的*
是解包运算符。可以将其视为将其参数转储到函数
zip(ints, ints)
那么zip
实际上在做什么? zip
的正常用法是采用两个迭代并将元素配对,就像这样。
list(zip([1,2,3], [4,5,6])) #put the results from zip into a list
[(1, 4), (2, 5), (3, 6)]
它也适用于两个以上的列表,但这不是我们在这里的目的。
值得注意的是,在zip(ints, ints)
中,两个ints
参数是同一个对象。这意味着当zip创建第一对时,它首先从第一个参数ints
获取下一个元素。那是36
。然后它从第二个参数中获取下一个元素,该元素是相同的ints
。所以下一个元素是30
。然后它在元组中产生这两个元素,然后继续为迭代器的其余部分重复该过程。
如果您问自己"为什么在zip(*[iter(ints)]*2)
表示相同的事情时写zip(ints, ints)
?"它是因为你必须确保参数是同一个对象,否则它不起作用。执行zip(iter(ints),iter(ints))
不会起作用,因为每个iter
都会返回一个不同但相同的迭代器。我无法记住何时必须使用iter
,所以为了安全起见,我只是一直使用它。
答案 1 :(得分:2)
另一种比帕特里克提议更不透明(虽然更冗长)的方法是:
>>> 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'
答案 2 :(得分:2)
如果这是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'
答案 3 :(得分:1)
你可以这样做:
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
可能你想检查,len(nums)是偶数。如果不是,则抛出IndexError。
答案 4 :(得分:0)
您可以使用 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
答案 5 :(得分:0)
您可以在步骤2
中使用带范围的循环 for i in range(0, 6, 2):
do something to el[i] and el[i+1]
这样你就可以告诉程序转到想要的索引。这里我在循环中将得到值:[0,2,4]
答案 6 :(得分:0)
另一种解决方案:
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)
输出: BAT
答案 7 :(得分:0)
帕特里克回答略有改动。
>>> 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'
答案 8 :(得分:0)
您可以使用扩展列表切片来获取相邻数字对:
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
然后你可以使用zip
配对要加总的一半:
pairs = zip(firsthalf, secondhalf)
然后你可以在巴黎的每一部分上映射sum
:
ordinals = [sum(x) for x in pairs]
最后转换为字符串,调用:
print(''.join([chr(x) for x in ordinals])) #prints: 'BAT'
答案 9 :(得分:0)
很多方法可以做到这一点,但是如果不创建许多中间列表,你可以简单地创建一个迭代器并使用生成器来构造字符串:
>>> s = '36 30 25 40 80 4'
>>> i = iter(map(int, s.split()))
>>> ''.join(chr(sum(x)) for x in zip(i, i))
'BAT'
答案 10 :(得分:0)
您可以将字符串转换为返回整数的迭代器,并在列表解析中使用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这个有点清洁,因为没有明确的索引。