【问题标题】:two dimensional array for encryption in pythonpython中用于加密的二维数组
【发布时间】:2015-11-26 00:03:28
【问题描述】:

我想让用户制作一张任何必要大小的表格。首先他会输入行数和列数,然后他会为每列和每行输入一对数字,然后在剩余的单元格中输入数据。这是一个例子:

row\column|  23  |  54  |  34  |  75
-------------------------------------
   65     |  AM  |   h  |   9  |  C
-------------------------------------
   78     |  56  |   in |   13 |  ok

所以基本上在输入所有信息后,他应该能够说 7834 并得到 13,反之亦然(例如输入 9C 并得到 65346575)。

我试过这个,我明白为什么它不起作用,但这是我唯一的想法。

nc = int(raw_input('Input number of columns: '))
nr = int(raw_input('Input number of rows: '))

table = [[raw_input('Input two digits for each column: ') for i in range(2, nc)] for i in range(1)]
table = [[raw_input('Input two digits for each row: ') for i in range(1)] for i in range(2, nr)]
table = [[raw_input('Input data: ') for i in range(2, nc)] for i in range(2, nr)]

感谢任何帮助。

【问题讨论】:

  • 您将table 的值设置为三个不同的值。这就是你想要的吗?
  • 不,我希望它是一张桌子。我只是不知道如何将第一行和第一列与表格的其余部分分开,因为数据不同。

标签: python arrays


【解决方案1】:

我冒昧地将你所有的整数都保留为字符串,因为你表现出将它们连接在一起的趋势。

如果您真的想要一个可转置的二维数组,那么最不痛苦(并且非常强大)的解决方案是使用 numpy 数组。如果您尚未安装 numpy,则必须安装,但由于您没有为扩展库指定任何限制,我认为此解决方案是可以接受的。

数组索引从 0 开始,只接受整数。有ways 有一个带有自定义索引的数组,例如23, 54, 34, 75 而不是0, 1, 2, 3。如果你决定继承 numpy.array 并重写它的许多方法,it may get more convoluted that expected

相反,我提供了创建一个包装类的解决方案,该类可以处理您的自定义索引,但不能进行切片(无论如何,这在您的情况下可能是无稽之谈)。在后台,当您请求“6523”时,它会将其拆分为 2 位字符串,“65”和“23”,然后在行/列列表中查找它们的位置。在这种情况下,它将是 (0, 0)。现在您可以使用该数组索引来获取所需的元素。查找元素的索引以相反的方式工作。我们在任何时候都不会直接与数组结构进行交互,因此不需要重写它的任何方法。

代码

import numpy as np

class CustomIndexTable:
    def __init__(self, rows, columns, elements):
        self.rows = rows
        self.columns = columns
        self.data = np.array(elements, dtype=object)
        self.data = self.data.reshape((len(rows), len(columns)))

    def __getitem__(self, index):
        x, y = index[:2], index[2:]
        return self.data[self.rows.index(x),self.columns.index(y)]

    def __setitem__(self, index, element):
        x, y = index[:2], index[2:]
        self.data[self.rows.index(x),self.columns.index(y)] = element

    def _where(self, element):
        x, y = np.where(self.data == element)
        return self.rows[x] + self.columns[y]

    def transpose(self):
        self.rows, self.columns = self.columns, self.rows
        self.data = self.data.T

    def where(self, sequence):
        elements = []
        start = 0
        for end in xrange(1, len(sequence)+1):
            if sequence[start:end] in self.data:
                elements.append(sequence[start:end])
                start = end
        return ''.join(self._where(e) for e in elements)

def input_matrix_data(text):
    return raw_input(text).split()

col_indices = input_matrix_data("Column indices: ")
row_indices = input_matrix_data("Row indices: ")
data = input_matrix_data("All data, sorted by row: ")

table = CustomIndexTable(row_indices, col_indices, data)

评论

您不希望用户在输入新元素时重复表索引,例如为 (65, 23) 和 (65, 54) 重复 65。您可以简单地要求用户输入一次列和行索引,稍后我们将构建单独的表坐标。对于数据,让用户像阅读书中的行一样一次性输入,即从左到右逐行输入。对于所有输入,用户应使用空格分隔各个成员。比如输入列索引时,他应该写

23 54 34 75

对于数据

AM h 9 C 56 in 13 ok

一旦我们将数据放入一维列表中,我们就可以将它们放入一个数组中,并使用每行指定的列数将其重塑为二维。

类的结构对功能做出了一些假设,这些假设在您的问题中是隐含的。

  • 所有行/列标签均为 2 位整数(为方便起见,采用字符串格式)。
  • 没有两个或多个同名的表/行/列元素,因为list.index()numpy.where() 在这种情况下可能不会像您期望的那样运行。这个假设是有道理的,因为您的表的使用似乎是为了加密/解密,因此,每个元素都应该唯一地映射到另一个元素。
  • 在搜索元素序列的索引时,它假定表中没有元素是另一个元素的前缀,即“9”和“97”。

用法

一旦你构建了你的表,你就可以查看数据(不要直接编辑数组!),

>>> table.data
array([['AM', 'h', '9', 'C'],
       ['56', 'in', '13', 'ok']], dtype=object)

访问特定元素,

>>> table['7834']
'13'

为元素设置新值,

>>> table['7834']  = 'B'
>>> table['7834']
'B'

找到元素所在的位置,

>>> table.where('9')   # this should work equally well for '9C'
'6534'

或永久转置数组。

>>> table.transpose()
>>> table.where('9')
'3465'

最后,您可以向此类添加更多方法以满足您的需求,例如创建表后添加/删除整行元素。

【讨论】:

  • 如果我不需要它成为以后可以转置的真实表格,这对我来说非常有用。这很容易做到吗?
  • @shomz 我已经完全改变了我的答案以更好地满足您的需求。
  • 有一些简单的方法可以使self.dataself.rowsself.columns 对外部人员只读而在类内部可写。但是,这会扩展代码并且是不必要的,除非您希望您的用户爱管闲事并可能破坏他们自己的数据。
  • 感谢您如此详尽的回答
  • 我试图通过一个菜单来完成这项工作,用户可以在其中选择形成表格、加密、解密、更改行或列标题的值或转置,但我只是无法让它工作..你有没有机会帮助我?可能值得一提的是,用户可以做不止一件事(例如,他可以形成表格、转置,然后解密某些东西)
【解决方案2】:

那样做是行不通的。

实际上,我有点撒谎。它会这样工作(我对你写的生成器有问题):

>>> table = [[raw_input('Input data: ') for i in range(1, nc+1)] for i in         range(1, nr+1)]
Input data: 1
Input data: 2
Input data: 3
Input data: 4
Input data: 5
Input data: 6 
Input data: 7 
Input data: 8
Input data: 9
>>> table
[['1', '2', '3'], ['4', '5', '6'], ['7', '8', '9']]

但这正是您一开始所要求的——您似乎希望最终用户能够输入列标题和行标题,然后填充数据。

如果我们:

table = [[raw_input('Input data: {},{} '.format(a,b)) for a in range(0, nc)] for b in range(0, nr)]

那么我们可以得到:

Input data: 0,0 None
Input data: 1,0 1
Input data: 2,0 2
Input data: 0,1 a
Input data: 1,1 Ted
Input data: 2,1 Fred
Input data: 0,2 b
Input data: 1,2 3.214
Input data: 2,2 Copy
>>> table
[['None', '1', '2'], ['a', 'Ted', 'Fred'], ['b', '3.214', 'Copy']]

现在,您的方案中混乱的部分是,要在“网格”中找到坐标,您必须读取每个列标题并取回它的位置,然后读取每一行标题以取回 它是 em>位置。那么你可以:

值 = 网格[r][c]

现在,逆向操作更加困难——您必须阅读每个单元格才能取回行标题和列标题。

哦,我们没有进行任何错误检查,以确保您输入的 2 行或标题不一样,这会彻底破坏您的计划。你会需要那个。

此外,填写该网格需要大量工作。

剩下的就是我在没有生成器的情况下胡思乱想,并犯了一些教育错误。

如果你想使用列表列表:

row = [None for i in range(0,nc+1)]
grid = [row for i in range(0,nr+1)]

然后,这会为您提供一个列表,其中包含无填充的列表。

>>> grid
[[None, None, None, None], [None, None, None, None], [None, None, None, None], [None, None, None, None]]

好的,所以输入列标题:

>>> for ch in range (1,nc+1):
...     grid[0][ch] = raw_input("Header, Column {}".format(ch))
...
Header, Column 111
Header, Column 222
Header, Column 333
>>> grid
[[None, '11', '22', '33'], [None, '11', '22', '33'], [None, '11', '22', '33'], [None, '11', '22', '33']]

咦,怎么没用?

>>> grid[0][3]="steve"
>>> grid
[[None, '11', '22', 'steve'], [None, '11', '22', 'steve'], [None, '11', '22', 'steve'], [None, '11', '22', 'steve']]

哦,是的。

臭虫。

import copy
row = [None for i in range(0,nc+1)]
grid = [copy.deepcopy(row) for i in range(0,nr+1)]
>>> for ch in range (1,nc+1):
...     grid[0][ch] = raw_input("Header, Column {}: ".format(ch))
...
Header, Column 1: 11
Header, Column 2: 22
Header, Column 3: 33
>>> grid
[[None, '11', '22', '33'], [None, 5, None, None], [None, None, None, None], [None, None, None, None]]

(忽略5,那是我测试的)

然后是行:

>>> for rh in range(1,nr+1):
...     grid[rh][0] = raw_input("Row Header: {} ".format(rh))
...
Row Header: 1 11
Row Header: 2 22
Row Header: 3 33
>>> grid
[[None, '11', '22', '33'], ['11', 5, None, None], ['22', None, None, None], ['33', None, None, None]]

所以现在你用数据填充它(留作练习,因为它很明显)。

【讨论】:

  • 能否详细说明如何根据单元格中的数据获取行和列标题,反之亦然?
  • 是的,列标题始终是该列的第 0 行的内容,而行始终是该行的第 0 列。因此,当您找到与您要查找的内容匹配的单元格 [x,y] 时,[0,y] 是其中一个的标题,而 [x,0] 是另一个的标题。至少我认为。
猜你喜欢
  • 2020-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 2012-03-09
  • 2012-01-01
相关资源
最近更新 更多