Python 如何将由可打印字符组成的字符串映射到INT

Python 如何将由可打印字符组成的字符串映射到INT,python,Python,我从古腾堡计划下载了一本书。对于一个编码项目,我需要将每个单词映射到一个正整数。单词中的字母都可以打印,但本书使用的完整字母表大小为75。这包括标点符号 如何将每个单词映射为整数?同一个字应始终映射到同一个整数,但不同的字应映射到不同的整数 输入是一个单词列表。例如: '[', 'Emma', 'by', 'Jane', 'Austen', '1816', ']', 'VOLUME', 'I', 'CHAPTER',... 理想情况下,我希望避免仅仅为了映射第一个单词而读取整个输入。使用set

我从古腾堡计划下载了一本书。对于一个编码项目,我需要将每个单词映射到一个正整数。单词中的字母都可以打印,但本书使用的完整字母表大小为75。这包括标点符号

如何将每个单词映射为整数?同一个字应始终映射到同一个整数,但不同的字应映射到不同的整数

输入是一个单词列表。例如:

'[', 'Emma', 'by', 'Jane', 'Austen', '1816', ']', 'VOLUME', 'I', 'CHAPTER',...

理想情况下,我希望避免仅仅为了映射第一个单词而读取整个输入。

使用
set
enumerate

words = ['[', 'Emma', 'by', 'Jane', 'Austen', '1816', ']', 'VOLUME', 'I', 'CHAPTER']
{word: idx for idx, word in enumerate(set(words))}
您需要阅读整个输入,以了解文本中的所有独特单词

编辑

添加了删除标点符号和文本小写的功能

from gutenberg.acquire import load_etext
from gutenberg.cleanup import strip_headers
import string

text = strip_headers(load_etext(158)).strip() # download http://www.gutenberg.org/ebooks/158
punctuation = string.punctuation + '“”'
text = text.lower().translate(str.maketrans(punctuation, ' ' * len(punctuation))) # strip punctuation 
words = sorted(set(text.split()))
{word: idx for idx, word in enumerate(words)}
输出:

{'000': 0,
 '10': 1,
 '23rd': 2,
 '24th': 3,
 '26th': 4,
 '28th': 5,
 '7th': 6,
 '8th': 7,
 'a': 8,
 'abbey': 9,
 'abbots': 10,
 'abdy': 11,
 'abhor': 12,
 'abhorred': 13,
 'abide': 14,
 'abilities': 15,
 'able': 16,
 'abode': 17,
 'abolition': 18,
 'abominable': 19,
 'about': 20,
 ...
 'you': 7088,
 'young': 7089,
 'younger': 7090,
 'youngest': 7091,
 'your': 7092,
 'yours': 7093,
 'yourself': 7094,
 'youth': 7095,
 'youthful': 7096,
 'zeal': 7097,
 'zigzags': 7098}
演示:


根据您的用例,可能会有一些调整。例如,如果希望
WordMap
不区分大小写,则只能将小写版本的单词添加到
self中。

我会按照下面的方法进行操作(如果大数字不是问题),请使用
ascii
对其进行编码(如果文本限于ascii字符)或
utf-8
然后将这些字节视为整数,即:

def get_code(x):
    return int.from_bytes(x.encode('ascii'), 'big')
words = ['[', 'Emma', 'by', 'Jane', 'Austen', '1816', ']', 'VOLUME', 'I', 'CHAPTER']
for w in words:
    print(w, get_code(w))
输出

[ 91
Emma 1164799329
by 25209
Jane 1247899237
Austen 71972703987054
1816 825766198
] 93
VOLUME 94898583063877
I 73
CHAPTER 18938268797388114
EMMA 26707
BY 652
JANE 97380
AUSTEN 168989055
VOLUME 65725188
I 9
CHAPTER 5629312471
请记住,此方法不会产生尽可能小的值。如果您事先知道所有字符,另一种可能是在提供订单后将其视为数字。考虑更简单的例子:获取由大写字母ASCII字母组成的代码,如<代码> 26 <代码>,意味着使用<代码> BASE-26系统,因此

chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def get_code(word):
    values = [chars.index(i)+1 for i in word]
    return sum(v*26**inx for inx, v in enumerate(values))
words = ['EMMA', 'BY', 'JANE', 'AUSTEN', 'VOLUME', 'I', 'CHAPTER']
for w in words:
    print(w, get_code(w))
输出

[ 91
Emma 1164799329
by 25209
Jane 1247899237
Austen 71972703987054
1816 825766198
] 93
VOLUME 94898583063877
I 73
CHAPTER 18938268797388114
EMMA 26707
BY 652
JANE 97380
AUSTEN 168989055
VOLUME 65725188
I 9
CHAPTER 5629312471


您可以选择使用不同的结尾。

使用?@Tomerikoo理想情况下,我希望不必为了映射第一个单词而处理整个文件。为什么您需要处理整个文件?只要
hash
第一个单词…@Anush您可以为这些95创建顺序,并将单词视为用base-95编写的整数system@Anush存在32位哈希函数,它是内置模块中的
zlib.adler32
,返回无符号32位整数。理想情况下,我希望避免为了映射第一个单词而必须处理整个文件。这些可以成为正整数吗?我肯定也需要能够处理标点符号。为什么你的方法不处理标点符号?我添加了标点符号剥离。我可以将整数设为正数,但不能再保证它们是唯一的(有可能发生哈希冲突)。再次用我的set+enumerate实现替换哈希谢谢。这是一个很好的答案。考虑到只有95个可打印字符,这可以用来减少整数的大小吗?也许
导入字符串;chars=string。可打印的
将解决此问题。我的示例是为清晰起见而设计的,您可以将其用于任何字符,方法是将
字符替换为包含所有可能字符的字符串(仅一次)和所述字符串长度的26。谢谢您的回答,非常好。我希望我能接受两个答案!这似乎完美地代表了所有的要求:同一个单词总是映射到同一个数字,没有两个单词共享同一个数字,这将产生尽可能最小的数字。哦,唯一的缺点是你必须阅读整个文件实际上也许你也不需要阅读整个文件。你一读入第一个单词就可以得到它的映射。@Anush我在想,如果你只想要第34个单词,比如当映射被初始化时会怎么样。但是,在程序的单个实例中,这仍然确保了需求。这些值可能会发生变化,但它们仍然是唯一的,无论您使用的词的顺序如何access@Tomerikoo我认为价值观也不会改变。我的意思是,一旦一个单词被映射到int,它将永远保持这种映射。@Anush我的意思是,对于程序的两次不同运行,一个特定单词可能具有不同的值,这取决于您读取文件的顺序。但由于我不知道您的确切用例,我可能在胡说八道。。。