Pythonic方式获取两个列表相交的项的索引

时间:2018-02-13 00:38:40

标签: python list

说我有两个列表:一个是字符串 - '示例'另一个是字母表。我希望找到一种更加pythonic的方式,其中字母表中的每个位置都列出了字符串列表中的每个字母'示例'相交并将这些索引放在一个列表中。  I.E.

  • e:4
  • x:23
  • a:0
  • m:12

等...

到目前为止,我有:

film_id

我尝试过使用set intersection,但字符串' key'每个字母可以包含多个字母,我正在查找索引,而不是哪个字母匹配。

到目前为止,我所尝试的最好的是:

import string
alphabet = list(string.ascii_lowercase)
key = list('example')

def convert(string, alphabet):
    table_l = []
    for char in string:
        for letter in alphabet:
            if letter == char:
                table_l.append(alphabet.index(letter))
    return table_l

convert(key, alphabet)

我不知道如何附加字母键,其中值与每个键的字母相交。

由于

5 个答案:

答案 0 :(得分:2)

您希望映射从字母到数字,因此请使用映射数据结构,例如dict

>>> alphamap = dict(zip(alphabet, range(len(alphabet)))
>>> alphamap
{'h': 7, 'e': 4, 'g': 6, 'n': 13, 'm': 12, 's': 18, 'x': 23, 'r': 17, 'o': 14, 'f': 5, 'a': 0, 'v': 21, 't': 19, 'd': 3, 'j': 9, 'l': 11, 'b': 1, 'u': 20, 'y': 24, 'q': 16, 'k': 10, 'c': 2, 'w': 22, 'p': 15, 'i': 8, 'z': 25}
>>> def convert(string, map_):
...     return  [map_[c] for c in string]
...
>>> convert('example', alphamap)
[4, 23, 0, 12, 15, 11, 4]

请注意,您的原始方法可以简化为:

>>> list(map(alphabet.index, 'example'))
[4, 23, 0, 12, 15, 11, 4]

然而,使用alphabet.index的效率低于使用映射(因为它必须每次都进行线性搜索而不是常量时间哈希)。

另外,请注意我直接迭代字符串,不需要将它们放入列表中,字符串是序列就像list个对象一样。它们可以迭代,切片等。但是,它们是不可变的。

最后,如果没有相应的值,上述方法将失败,即一个特殊的非字母字符。

>>> convert("example!", alphamap)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in convert
  File "<stdin>", line 2, in <listcomp>
KeyError: '!'

这可能是也可能不是。或者,您可以使用带有默认值的.get来解决此问题,例如:

>>> def convert(string, map_, default=-1):
...     return  [map_.get(c, default) for c in string]
...
>>> convert("example!", alphamap)
[4, 23, 0, 12, 15, 11, 4, -1]

答案 1 :(得分:1)

如果它都是ascii,那么下面的东西应该可以工作 - 将字母转换为数字表示,然后在ascii中将97减去为'a'

a = ord(‘a’)
[ord(c)-a for c in ‘example’.lower()]

答案 2 :(得分:1)

以某种方式和盖伊一样精神,如何计算基数36(并遵循DyZ&m;和mhawke的建议),

>>> a = int('a', 36)
>>> [int(c, 36) - a for c in 'example']
[4, 23, 0, 12, 15, 11, 4]

<小时/> 请注意,此方法不区分大小写,并且如果它都是ascii(在您使用string.ascii_lowercase后似乎就是这种情况),则会起作用。

答案 3 :(得分:0)

使用套装。

overlapKeys = set(alphabet) & set(key)
listOfIndices = [alphabet.index(key) for key in overlapKeys]

此外,

key = list('example')

是不必要的。字符串是字符列表。使用

key = 'example'

答案 4 :(得分:0)

你的例子似乎有点偏离......不会m是23,>>> s = 'example' >>> [(c, string.ascii_lowercase.index(c)) for c in s] # as a list of tuples [('e', 4), ('x', 23), ('a', 0), ('m', 12), ('p', 15), ('l', 11), ('e', 4)] 12等?

index()

对于较长的字符串,这会有点低效,因为使用# create a dict that maps characters to indices indices = {c: index for index, c in enumerate(string.ascii_lowercase)} # perform the conversion >>> s = 'example' >>> [(c, indices.get(c, -1)) for c in s] [('e', 4), ('x', 23), ('a', 0), ('m', 12), ('p', 15), ('l', 11), ('e', 4)] 有效地使这成为O(n ** 2)解决方案。

更好的方法是使用查找字典将字符转换为索引。因为dict查找是O(1),所得到的解决方案将是O(n),这要好得多。

>>> [indices.get(c, -1) for c in s]
[4, 23, 0, 12, 15, 11, 4]

如果您只想要指数:

#include <iostream>
#include <fstream>

void encrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0, i;           /* set up */
    uint32_t delta = 0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];   /* cache key */
    for (i = 0; i < 32; i++) {                       /* basic cycle start */
        sum += delta;
        v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
    }                                              /* end cycle */
    v[0] = v0; v[1] = v1;
}

void decrypt(uint32_t* v, uint32_t* k) {
    uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;  /* set up */
    uint32_t delta = 0x9e3779b9;                     /* a key schedule constant */
    uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];   /* cache key */
    for (i = 0; i<32; i++) {                         /* basic cycle start */
        v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
        v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
        sum -= delta;
    }                                              /* end cycle */
    v[0] = v0; v[1] = v1;
}

int main()
{
    uint32_t k[4] = { 123,456,789,10 }; // key
    uint32_t v[2] = { 1000000, 1000000 }; // data


    // save into file
    std::ofstream ofs("save.dat", std::ios::binary);
    encrypt(v, k);
    ofs << v[0] << " " << v[1] << std::endl;



    // read from file
    std::ifstream ifs("save.dat", std::ios::binary);
    uint32_t v2[2];

    if (ifs >> v2[0] >> v2[1])
    {
        std::cout << "Filedata: " << v2[0] << " " << v2[1] << std::endl;

        decrypt(v2, k);

        if (v2[0] == v2[1])
            std::cout << "Decrypted: " << v2[0] << std::endl;
        else
            std::cout << "Data was tampered with!" << std::endl;
    }
}