关于python:如何将数字列表拆分并插入到另一个列表中

How to get a split up a list of numbers and insert into another list

目前我有一个文件,有6行数字,每行包含9个数字。关键是测试文件中每一行数字,如果它完成了一个魔方。例如,假设文件中的一行数字是4 3 8 9 5 1 2 7 6。前三个数字必须是矩阵中的第一行。接下来的三个数字需要是第二行,第三行也一样。因此,您需要得到一个矩阵:['4'、'3'、'8']、['9'、'5'、'1']、['2'、'7'、'6']

我需要测试这个矩阵,看看它是否是一个有效的魔方(行加15,列加15,对角线加15)。

我的代码当前为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def readfile(fname):
   """Return a list of lines from the file"""
    f = open(fname, 'r')
    lines = f.read()
    lines = lines.split()
    f.close()
    return lines

def assignValues(lines):
    magicSquare = []
    rows = 3
    columns = 3
    for row in range(rows):
        magicSquare.append([0] * columns)
    for row in range(len(magicSquare)):
        for column in range(len(magicSquare[row])):
            magicSquare[row][column] = lines[column]
    return magicSquare

def main():
    lines = readfile(input_fname)
    matrix = assignValues(lines)
    print(matrix)

每当我运行代码来测试它时,我都会得到:

1
[['4', '3', '8'], ['4', '3', '8'], ['4', '3', '8']]

所以你可以看到,我只是把前3个数放入我的矩阵中。最后,我的问题是,我将如何继续我的矩阵与以下6个数字行的数字?我不确定这是否是我在循环中可以做的事情,或者我的线路分裂错误,或者我完全走错了轨道?

谢谢。


要测试输入文件中的每一行是否包含幻方数据,您需要稍微重新组织代码。我用了一种不同的方法来填充矩阵。也许更难理解zip(*[iter(seq)] * size)是如何工作的,但这是一个非常有用的模式。如果你需要解释的话,请告诉我。

我的代码为矩阵使用了一个元组列表,而不是一个列表列表,但是无论如何,元组在这里更适合,因为矩阵中的数据不需要修改。另外,我将str的输入数据转换为int,因为您需要对数字进行算术运算以测试matrix是否是一个魔方。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#! /usr/bin/env python

def make_square(seq, size):
    return zip(*[iter(seq)] * size)


def main():
    fname = 'mydata'
    size = 3
    with open(fname, 'r') as f:
        for line in f:
            nums = [int(s) for s in line.split()]
            matrix = make_square(nums, size)
            print matrix
            #Now call the function to test if the data in matrix
            #really is a magic square.
            #test_square(matrix)


if __name__ == '__main__':
    main()

这里有一个修改过的make_square()版本,它返回列表而不是元组列表,但是请记住,如果不需要列表提供的可变性,元组列表实际上比列表列表更好。

1
2
3
def make_square(seq, size):
    square = zip(*[iter(seq)] * size)
    return [list(t) for t in square]

我想我应该提到,实际上只有一个可能的3x 3魔方使用了从1到9的所有数字,不计算旋转和反射。但我想,对这一事实进行一次蛮力的演示是没有坏处的。:)

另外,我还有几年前(当我第一次学习Python时)编写的Python代码,它生成了大小为n x n的魔法方块(奇数n>=5)。如果你想看,请告诉我。

zip和迭代器对象

下面是一些代码,简要说明了zip()和iter()函数的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
''' Fun with zip '''

numbers = [1, 2, 3, 4, 5, 6]
letters = ['a', 'b', 'c', 'd', 'e', 'f']

#Using zip to create a list of tuples containing pairs of elements of numbers & letters
print zip(numbers, letters)

#zip works on other iterable objects, including strings
print zip(range(1, 7), 'abcdef')

#zip can handle more than 2 iterables
print zip('abc', 'def', 'ghi', 'jkl')

#zip can be used in a for loop to process two (or more) iterables simultaneously
for n, l in zip(numbers, letters):
    print n, l

#Using zip in a list comprehension to make a list of lists
print [[l, n] for n, l in zip(numbers, letters)]

#zip stops if one of the iterables runs out of elements
print [[n, l] for n, l in zip((1, 2), letters)]
print [(n, l) for n, l in zip((3, 4), letters)]

#Turning an iterable into an iterator object using the iter function
iletters = iter(letters)

#When we take some elements from an iterator object it remembers where it's up to
#so when we take more elements from it, it continues from where it left off.
print [[n, l] for n, l in zip((1, 2, 3), iletters)]
print [(n, l) for n, l in zip((4, 5), iletters)]

#This list will just contain a single tuple because there's only 1 element left in iletters
print [(n, l) for n, l in zip((6, 7), iletters)]

#Rebuild the iletters iterator object
iletters = iter('abcdefghijkl')

#See what happens when we zip multiple copies of the same iterator object.
print zip(iletters, iletters, iletters)

#It can be convenient to put multiple copies of an iterator object into a list
iletters = iter('abcdefghijkl')
gang = [iletters] * 3

#The gang consists of 3 references to the same iterator object
print gang

#We can pass each iterator in the gang to zip as a separate argument
#by using the"splat" syntax
print zip(*gang)

#A more compact way of doing the same thing:
print zip(* [iter('abcdefghijkl')]*3)

下面是在交互式解释器中运行的相同代码,因此您可以轻松地看到每个语句的输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
>>> numbers = [1, 2, 3, 4, 5, 6]
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f']
>>>
>>> #Using zip to create a list of tuples containing pairs of elements of numbers & letters
... print zip(numbers, letters)
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]
>>>
>>> #zip works on other iterable objects, including strings
... print zip(range(1, 7), 'abcdef')
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]
>>>
>>> #zip can handle more than 2 iterables
... print zip('abc', 'def', 'ghi', 'jkl')
[('a', 'd', 'g', 'j'), ('b', 'e', 'h', 'k'), ('c', 'f', 'i', 'l')]
>>>
>>> #zip can be used in a for loop to process two (or more) iterables simultaneously
... for n, l in zip(numbers, letters):
...     print n, l
...
1 a
2 b
3 c
4 d
5 e
6 f
>>> #Using zip in a list comprehension to make a list of lists
... print [[l, n] for n, l in zip(numbers, letters)]
[['a', 1], ['b', 2], ['c', 3], ['d', 4], ['e', 5], ['f', 6]]
>>>
>>> #zip stops if one of the iterables runs out of elements
... print [[n, l] for n, l in zip((1, 2), letters)]
[[1, 'a'], [2, 'b']]
>>> print [(n, l) for n, l in zip((3, 4), letters)]
[(3, 'a'), (4, 'b')]
>>>
>>> #Turning an iterable into an iterator object using using the iter function
... iletters = iter(letters)
>>>
>>> #When we take some elements from an iterator object it remembers where it's up to
... #so when we take more elements from it, it continues from where it left off.
... print [[n, l] for n, l in zip((1, 2, 3), iletters)]
[[1, 'a'], [2, 'b'], [3, 'c']]
>>> print [(n, l) for n, l in zip((4, 5), iletters)]
[(4, 'd'), (5, 'e')]
>>>
>>> #This list will just contain a single tuple because there's only 1 element left in iletters
... print [(n, l) for n, l in zip((6, 7), iletters)]
[(6, 'f')]
>>>
>>> #Rebuild the iletters iterator object
... iletters = iter('abcdefghijkl')
>>>
>>> #See what happens when we zip multiple copies of the same iterator object.
... print zip(iletters, iletters, iletters)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('j', 'k', 'l')]
>>>
>>> #It can be convenient to put multiple copies of an iterator object into a list
... iletters = iter('abcdefghijkl')
>>> gang = [iletters] * 3
>>>
>>> #The gang consists of 3 references to the same iterator object
... print gang
[<iterator object at 0xb737eb8c>, <iterator object at 0xb737eb8c>, <iterator object at 0xb737eb8c>]
>>>
>>> #We can pass each iterator in the gang to zip as a separate argument
... #by using the"splat" syntax
... print zip(*gang)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('j', 'k', 'l')]
>>>
>>> #A more compact way of doing the same thing:
... print zip(* [iter('abcdefghijkl')]*3)
[('a', 'b', 'c'), ('d', 'e', 'f'), ('g', 'h', 'i'), ('j', 'k', 'l')]
>>>


它只得到前3列总是因为

1
magicSquare[row][column] = lines[column]

因此

1
2
3
4
5
6
7
8
9
10
11
def assignValues(lines):
    magicSquare = []
    rows = 3
    columns = 3
    for row in range(rows):
        magicSquare.append([0] * columns)
    for line in range((sizeof(lines)/9)) #since the input is already split this means that the size of 'lines' divided by 9 is equal to the number of rows of numbers
        for row in range(len(magicSquare)):
            for column in range(len(magicSquare[row])):
                magicSquare[row][column] = lines[(9*line)+(3*row)+column]
    return magicSquare

请注意,(3*行)+列将在每次迭代中向右移动3列而该(9*行)+(3*行)+列在每次迭代时都会向右移动9列(整行)

一旦你得到了这个,你现在就准备好去寻找魔方了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def testMagicSquare(matrix):
    rows = 3
    columns = 3
    for a in len(matrix)
        test1 = 0
        test2 = 0
        test3 = 0
        for b in range(3)
            if(sum(matrix[a][b])==15) test1=1 #flag true if whole row is 15 but turns false if a row is not 15
            else test1=0

            if((matrix[a][0][b]+matrix[a][1][b]+matrix[a][2][b])==15) test2=1 #flag true if column is 15 but turns false if a column is not 15
            else test2=0

            if(((matrix[a][0][0]+matrix[a][1][1]+matrix[a][2][2])==15) and
            ((matrix[a][0][2]+matrix[a][1][1]+matrix[a][2][0])==15)) test3=1 #flag true if diagonal  is 15 but turns false if diagonal is not 15
            else test3=0

        if(test1>0 and test2>0 and test3>0) println('line ' + a + ' is a magic square')
        else println('line ' + a + ' is not a magic square')