【问题标题】:Mapping modified string indices to original string indices in Python将修改后的字符串索引映射到 Python 中的原始字符串索引
【发布时间】:2014-10-01 03:51:39
【问题描述】:

我对编程比较陌生,想就遇到的问题寻求帮助。在删除某些位置后,我需要找出一种将字符串的索引映射回原始字符串的方法。例如,假设我有一个列表:

original_string = 'abcdefgh'

我删除了一些元素以获得:

new_string = acfh

我需要一种方法来获取new_string 的“真实”索引。换句话说,我想要我在original_string 中保留的位置的索引。从而返回:

original_indices_of_new_string = [0,2,5,7]

我的一般做法是这样的:

我在original_string 中找到了我删除的职位:

removed_positions = [1,3,4,6]

然后给定new_string的索引:

new_string_indices = [0,1,2,3]

那么我想我应该可以做这样的事情:

original_indices_of_new_string = []   
for i in new_string_indices:
        offset = 0
        corrected_value = i + offset
        if corrected_value in removed_positions:
            #somehow offset to correct value
            offset+=1
        else:
            original_indices_of_new_string.append(corrected_value)

这并没有真正起作用,因为偏移量在每次循环后重置为 0,我只想在 corrected_value 位于 removed_positions 中时发生这种情况(即,我想为 remove_positions 3 和 4 偏移 2 但是如果没有删除连续位置,则只有 1)。

我需要根据我删除的位置而不是我保留的位置来执行此操作,因为接下来我将删除更多位置,我希望有一个简单的函数将它们映射回每次都是原版。我也不能只搜索我删除的部分,因为真正的字符串不够独特,无法保证找到正确的部分。

任何帮助将不胜感激。我已经使用堆栈溢出有一段时间了,总是发现我在上一个线程中遇到的问题,但这次找不到问题,所以我决定自己发布一个问题!让我知道是否有任何需要澄清的地方。

*字符串中的字母不是唯一的

【问题讨论】:

  • 你如何决定首先删除哪些元素?
  • 字符串中的字母是否唯一?即,一个字母不会出现多次?
  • 字符串中的字母不是唯一的。我实际上使用的字符串相当长并且有很多重复。这是我一直试图解决的问题,以及为什么使用类似 string.index() 的东西不起作用。

标签: python string mapping indices


【解决方案1】:

给定您的字符串original_string = 'abcdefgh',您可以创建索引的元组和每个字符:

>>> li=[(i, c) for i, c in enumerate(original_string)]
>>> li
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e'), (5, 'f'), (6, 'g'), (7, 'h')]

然后删除你想要的字符:

>>> new_li=[t for t in li if t[1] not in 'bdeg']
>>> new_li
[(0, 'a'), (2, 'c'), (5, 'f'), (7, 'h')]

然后将其重新加入一个字符串:

>>> ''.join([t[1] for t in new_li])
acfh

您的“答案”是用于创建new_li 的方法并引用那里的索引:

>>> ', '.join(map(str, (t[0] for t in new_li)))
0, 2, 5, 7

【讨论】:

  • 谢谢!我不得不为我的实际目的进行一些修改,但这个想法很有效。
【解决方案2】:

你可以新建一个class来处理这个东西

class String:
def __init__(self, myString):
    self.myString = myString
    self.myMap    = {}
    self.__createMapping(self.myString)

def __createMapping(self, myString):
    index = 0
    for character in myString:
        # If the character already exists in the map, append the index to the list
        if character in self.myMap:
            self.myMap[character].append(index)
        else:
            self.myMap[character] = [index,]
            index += 1

def removeCharacters(self, myList):
    for character in self.myString:
        if character in myList:
            self.myString = self.myString.replace(character, '')
            del self.myMap[character]
    return self.myString

def getIndeces(self):
    return self.myMap




if __name__ == '__main__':
    myString = String('abcdef')
    print myString.removeCharacters(['a', 'b']) # Prints cdef
    print myString.getIndeces() # Prints each character and a list of the indeces these occur at

这将给出字符的映射和它们出现的索引列表。如果您想要返回单个列表等,您可以添加更多功能。希望这能让您了解如何开始

【讨论】:

    【解决方案3】:

    如果按索引删除,您只需从所有索引的列表开始,例如:[0, 1, 2, 3, 4],然后在每个索引处删除时,将其从该列表中删除。例如,如果您要删除索引 1 和 3,您将执行以下操作:

    idxlst.remove(1)
    idxlst.remove(3)
    idxlst  # => [0, 2, 4]
    

    [update]:如果不按索引删除,最简单的方法可能是先找到索引,然后继续上述解决方案,例如如果从 'abc' 中删除 'c',请执行以下操作:

    i = mystr.index('c')
    # remove 'c'
    idxlst.remove(i)
    

    【讨论】:

      【解决方案4】:

      尝试尽可能接近您最初尝试完成的任务,这段代码应该可以工作:

      big = 'abcdefgh'
      small='acfh'
      
      l = []
      current = 0
      while len(small) >0:
          if big[current] == small[0]:
              l.append(current)
              small = small[1:]
          else:
              current += 1
      print(l)
      

      这个想法是从正面开始的,因此您无需担心偏移。

      前提当然是small实际上是通过从big中删除一些索引得到的。否则,将抛出 IndexError。如果您需要代码更健壮,只需在最后捕获异常并返回一个空列表或其他内容。否则代码应该可以正常工作。

      【讨论】:

        【解决方案5】:

        假设您的输入字符串中的字符是唯一的,这就是您的代码所发生的情况:

        original_indices_of_new_string = []   
        for i in new_string_indices:
                offset = 0
                corrected_value = i + offset
                if corrected_value in removed_positions:
                    #somehow offset to correct value
                    offset+=1
                else:
                    original_indices_of_new_string.append(corrected_value)
        

        在循环中每次将offset 设置为0 与在循环外将其预设为0 一样好。如果您每次都在循环中将0 添加到i,不妨使用i。这将您的代码归结为:

        if i in removed_positions:
            #somehow offset to correct value
            pass
        else:
            original_indices_of_new_string.append(i)
        

        这段代码给出的输出为[0, 2],逻辑是正确的(再次假设输入中的字符是唯一的)你应该做的是,运行original_string 长度的循环。那会给你你想要的。像这样:

        original_indices_of_new_string = []
        for i in range(len(original_string)):
            if i in removed_positions:
                #somehow offset to correct value
                pass
            else:
                original_indices_of_new_string.append(i)
        print original_indices_of_new_string
        

        打印出来:

        [0, 2, 5, 7]

        实现相同目的的更简单的一种方法是:

        original_indices_of_new_string = [original_string.index(i) for i in new_string for j in i]
        

        希望这会有所帮助。

        【讨论】:

          【解决方案6】:

          将新字符串中的字符与它们在字典中原始字符串中的位置进行映射可能会有所帮助,并像这样恢复新字符串:

          import operator
          chars = {'a':0, 'c':2, 'f':6, 'h':8}
          sorted_chars = sorted(chars.iteritems(), key=operator.itemgetter(1))
          new_string = ''.join([char for char, pos in sorted_chars]) # 'acfh'
          

          【讨论】:

            猜你喜欢
            • 2019-08-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-04-23
            • 1970-01-01
            • 2013-01-11
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多