2017-01-16 5 views
0

Я индексация большого CSV (5000+ строки) файл в Python, используя следующий код:индексирования в словарь и Итерацию в Python

index = {} 
df = open('file.csv', encoding='UTF-8') 

fp = 0 
l = df.readline() 
while l: 
    r = l.split(',') 
    index[r[0]] = fp 
    fp = df.tell() 
    l = df.readline() 
df.seek(index["Sarah"]) 
print(df.readline()) 
df.close() 

Вот пример содержимого файла:

John, Always wears a blue hat 
Alex, Always wears a red shirt 
Sarah, Hates the colour pink 

Вот пример того, как они были проиндексированы:

{'John': 26389, 'Alex': 217059, 'Sarah': 142108...} 

Я пытаюсь добавить индексированные данные в двоичное дерево поиска, которое я построил с помощью учебника на интерактивном компьютере. Вот BST:

class TreeNode: 
    def __init__(self,key,val,left=None,right=None,parent=None): 
     self.key = key 
     self.payload = val 
     self.leftChild = left 
     self.rightChild = right 
     self.parent = parent 

    def hasLeftChild(self): 
     return self.leftChild 

    def hasRightChild(self): 
     return self.rightChild 

    def isLeftChild(self): 
     return self.parent and self.parent.leftChild == self 

    def isRightChild(self): 
     return self.parent and self.parent.rightChild == self 

    def isRoot(self): 
     return not self.parent 

    def isLeaf(self): 
     return not (self.rightChild or self.leftChild) 

    def hasAnyChildren(self): 
     return self.rightChild or self.leftChild 

    def hasBothChildren(self): 
     return self.rightChild and self.leftChild 

    def replaceNodeData(self,key,value,lc,rc): 
     self.key = key 
     self.payload = value 
     self.leftChild = lc 
     self.rightChild = rc 
     if self.hasLeftChild(): 
      self.leftChild.parent = self 
     if self.hasRightChild(): 
      self.rightChild.parent = self 


class BinarySearchTree: 

    def __init__(self): 
     self.root = None 
     self.size = 0 

    def length(self): 
     return self.size 

    def __len__(self): 
     return self.size 

    def put(self,key,val): 
     if self.root: 
      self._put(key,val,self.root) 
     else: 
      self.root = TreeNode(key,val) 
     self.size = self.size + 1 

    def _put(self,key,val,currentNode): 
     if key < currentNode.key: 
      if currentNode.hasLeftChild(): 
        self._put(key,val,currentNode.leftChild) 
      else: 
        currentNode.leftChild = TreeNode(key,val,parent=currentNode) 
     else: 
      if currentNode.hasRightChild(): 
        self._put(key,val,currentNode.rightChild) 
      else: 
        currentNode.rightChild = TreeNode(key,val,parent=currentNode) 

    def __setitem__(self,k,v): 
     self.put(k,v) 

    def get(self,key): 
     if self.root: 
      res = self._get(key,self.root) 
      if res: 
        return res.payload 
      else: 
        return None 
     else: 
      return None 

    def _get(self,key,currentNode): 
     if not currentNode: 
      return None 
     elif currentNode.key == key: 
      return currentNode 
     elif key < currentNode.key: 
      return self._get(key,currentNode.leftChild) 
     else: 
      return self._get(key,currentNode.rightChild) 

    def __getitem__(self,key): 
     return self.get(key) 

    def __contains__(self,key): 
     if self._get(key,self.root): 
      return True 
     else: 
      return False 

    def delete(self,key): 
     if self.size > 1: 
     nodeToRemove = self._get(key,self.root) 
     if nodeToRemove: 
      self.remove(nodeToRemove) 
      self.size = self.size-1 
     else: 
      raise KeyError('Error, key not in tree') 
     elif self.size == 1 and self.root.key == key: 
     self.root = None 
     self.size = self.size - 1 
     else: 
     raise KeyError('Error, key not in tree') 

    def __delitem__(self,key): 
     self.delete(key) 

    def spliceOut(self): 
     if self.isLeaf(): 
      if self.isLeftChild(): 
        self.parent.leftChild = None 
      else: 
        self.parent.rightChild = None 
     elif self.hasAnyChildren(): 
      if self.hasLeftChild(): 
        if self.isLeftChild(): 
        self.parent.leftChild = self.leftChild 
        else: 
        self.parent.rightChild = self.leftChild 
        self.leftChild.parent = self.parent 
      else: 
        if self.isLeftChild(): 
        self.parent.leftChild = self.rightChild 
        else: 
        self.parent.rightChild = self.rightChild 
        self.rightChild.parent = self.parent 

    def findSuccessor(self): 
     succ = None 
     if self.hasRightChild(): 
      succ = self.rightChild.findMin() 
     else: 
      if self.parent: 
       if self.isLeftChild(): 
        succ = self.parent 
       else: 
        self.parent.rightChild = None 
        succ = self.parent.findSuccessor() 
        self.parent.rightChild = self 
     return succ 

    def findMin(self): 
     current = self 
     while current.hasLeftChild(): 
      current = current.leftChild 
     return current 

    def remove(self,currentNode): 
     if currentNode.isLeaf(): #leaf 
      if currentNode == currentNode.parent.leftChild: 
       currentNode.parent.leftChild = None 
      else: 
       currentNode.parent.rightChild = None 
     elif currentNode.hasBothChildren(): #interior 
      succ = currentNode.findSuccessor() 
      succ.spliceOut() 
      currentNode.key = succ.key 
      currentNode.payload = succ.payload 

     else: # this node has one child 
      if currentNode.hasLeftChild(): 
      if currentNode.isLeftChild(): 
       currentNode.leftChild.parent = currentNode.parent 
       currentNode.parent.leftChild = currentNode.leftChild 
      elif currentNode.isRightChild(): 
       currentNode.leftChild.parent = currentNode.parent 
       currentNode.parent.rightChild = currentNode.leftChild 
      else: 
       currentNode.replaceNodeData(currentNode.leftChild.key, 
            currentNode.leftChild.payload, 
            currentNode.leftChild.leftChild, 
            currentNode.leftChild.rightChild) 
      else: 
      if currentNode.isLeftChild(): 
       currentNode.rightChild.parent = currentNode.parent 
       currentNode.parent.leftChild = currentNode.rightChild 
      elif currentNode.isRightChild(): 
       currentNode.rightChild.parent = currentNode.parent 
       currentNode.parent.rightChild = currentNode.rightChild 
      else: 
       currentNode.replaceNodeData(currentNode.rightChild.key, 
            currentNode.rightChild.payload, 
            currentNode.rightChild.leftChild, 
            currentNode.rightChild.rightChild) 

Я могу добавить отдельные элементы с помощью команды:

mytree = BinarySearchTree() 
mytree[1] = "One" 

То, что я пытаюсь сделать, это итерация по словарю индекса, но я получаю сообщение об ошибке.

Вот как я итерация словаря:

for k, v in index.items(): 
    mytree[k] = v 
+2

полный стокtrace пожалуйста. –

+0

Спасибо за ответ. Как мне это сделать? – 128K

+2

Я выхожу на конечность и предполагаю, что это строка с ошибкой: 'if key

ответ

1

Я думаю, что вы имеете в виду, чтобы сделать это, чтобы добавить элементы в бинарном дереве на основе их положения в формате CSV. Если это так, попробуйте добавить элемент на основе их значения (вместо ключа).

for k, v in index.items(): 
    mytree[v] = k 

EDIT: На основе комментариев, похоже, что ОП пытается ввести элементы в дереве на основе их имен (а не значения). Чтобы поймать, какая пара значений ключа вызывает это исключение, как насчет добавления этого кода? Это по крайней мере сузило проблему до конкретной пары ключ-значение, вызывающей это исключение. Одним из возможных вариантов является то, что ключ в некоторых случаях является строка, а в других случаях может быть Int (только предположение!)

def _put(self,key,val,currentNode): 
    try: 
     if key < currentNode.key: 
      if currentNode.hasLeftChild(): 
       self._put(key,val,currentNode.leftChild) 
      else: 
       currentNode.leftChild = TreeNode(key,val,parent=currentNode) 
     else: 
      if currentNode.hasRightChild(): 
       self._put(key,val,currentNode.rightChild) 
      else: 
       currentNode.rightChild = TreeNode(key,val,parent=currentNode) 
    except TypeError as e: 
     print "key = ", key 
     print "currentNode key = ", currentNode.key 
     print "val = ", val 
     raise e 
+0

Это работает, чтобы получить данные в двоичном дереве, но я не могу искать его по имени таким образом, или я могу? – 128K

+1

Если вы хотите найти что-то по имени, используйте dict. – stark

+0

Он находится в словаре перед его добавлением в BST, используя следующий формат '{name: index number in csv}' Если я импортирую его в BST с помощью значения вместо ключа, я не могу выполнить поиск в BST с помощью ключа могу я? – 128K

1

Вы получаете сообщение об ошибке, как только некоторые из ключей являются Интс и некоторые строки , они не сопоставимы, так что это не сработает.

ли вы на самом деле использовать линию

ytree[1] = "One" 

? Поскольку это использует ключ int, а остальная часть кода вставляет строки как ключи. Это должно было быть наоборот.

+0

есть ли более подходящий способ использования индекса CSV и добавления в BST? – 128K

+0

@ 128K: Мне не хватает _why_ вы делаете BST, это просто упражнение? – RemcoGerlich

+0

Это упражнение в основном играть с BST и посмотреть, как они работают – 128K