2014-03-25 46 views

回答

3

运行这一系列更新换代:

  • ( - ><ul><li>
  • ) - ></ul></li>
  • , - ></li><li>

然后在浏览器


打开它,或者如果它是一个Python对象,使用pprint:

>>> x = ((("A","B"),("C","D")),"E") 
>>> from pprint import pprint 
>>> pprint(x, width=1) 
((('A', 
    'B'), 
    ('C', 
    'D')), 
'E') 

或自定义的Python的解决方案:

from itertools import izip 

def first_then(first, then): 
    yield first 
    while True: 
     yield then 

def tree_lines(x): 
    if type(x) is tuple: 
     if len(x) == 1: 
      # singular tuple 
      for p, l in izip(first_then('--', ' '), tree_lines(x[0])): 
       yield p + l 
     else: 
      first, rest, last = x[0], x[1:-1], x[-1] 

      # first entry 
      for p, l in izip(first_then('T-', '| '), tree_lines(first)): 
       yield p + l 

      # middle entries 
      for y in rest: 
       for p, l in izip(first_then('>-', '| '), tree_lines(y)): 
        yield p + l 

      # last entries 
      for p, l in izip(first_then('L-', ' '), tree_lines(last)): 
       yield p + l 
    else: 
     yield str(x) 

x = ((('A','B'),('C','D')),'E') 

for l in tree_lines(x): 
    print(l) 
2

前阵子我写了一些用于制作树木文本表示的东西。这可能适合在这里。

class Node: 
    def __init__(self, value): 
     self.value = value 
     self.children = [] 


pipe = chr(179) 
t = chr(195) 
l = chr(192) 
backwards_r = chr(191) 

def printable(node, seq_is_last_child = []): 
    """returns a string representation of the given node""" 
    ret = "" 
    if seq_is_last_child: 
     for b in seq_is_last_child[:-1]: 
      if b: 
       ret = ret + " " 
      else: 
       ret = ret + pipe + " " 
     if seq_is_last_child[-1]: 
      ret = ret + l + " " 
     else: 
      ret = ret + t + " " 
    ret = ret + node.value 
    for idx, c in enumerate(node.children): 
     ret = ret + "\n" + printable(c, seq_is_last_child + [idx == len(node.children)-1]) 
    return ret 

def make_node(t): 
    """creates a Node system from a nested tuple""" 
    ret = Node(backwards_r) 
    for child in t: 
     if isinstance(child, str): 
      ret.children.append(Node(child)) 
     else: 
      ret.children.append(make_node(child)) 
    return ret 

x = ((('A','B'),('C','D')),'E') 
print printable(make_node(x)) 

结果:

┐ 
├ ┐ 
│ ├ ┐ 
│ │ ├ A 
│ │ └ B 
│ └ ┐ 
│ ├ C 
│ └ D 
└ E 

编辑:Unicode版本:

class Node: 
    def __init__(self, value): 
     self.value = value 
     self.children = [] 

def printable(node, seq_is_last_child = []): 
    """returns a string representation of the given node""" 
    ret = "" 
    if seq_is_last_child: 
     for b in seq_is_last_child[:-1]: 
      if b: 
       ret = ret + " " 
      else: 
       ret = ret + "│ " 
     if seq_is_last_child[-1]: 
      ret = ret + "└ " 
     else: 
      ret = ret + "├ " 
    ret = ret + node.value 
    for idx, c in enumerate(node.children): 
     ret = ret + "\n" + printable(c, seq_is_last_child + [idx == len(node.children)-1]) 
    return ret 

def make_node(t): 
    """creates a Node system from a nested tuple""" 
    ret = Node("┐") 
    for child in t: 
     if isinstance(child, str): 
      ret.children.append(Node(child)) 
     else: 
      ret.children.append(make_node(child)) 
    return ret 

x = ((('A','B'),('C','D')),'E') 
print printable(make_node(x)) 
+1

也许你应该使用unicode。在我的机器上'chr(179)=='³''。 ASCII是7位,只能达到127. – Hyperboreus

+0

@Hyperboreus,你是对的。我已经添加了一个Unicode版本。 – Kevin

1

可以使用迭代函数,发现depth和每个点的height

def locate(xs, depth, cnt): 
    from functools import partial 
    if isinstance(xs, str): 
     return dict(depth=depth, height=- next(cnt), inner=None, txt=xs) 
    else: 
     fn = partial(locate, depth=depth+1, cnt=cnt) 
     loc = list(map(fn, xs)) 
     height = np.mean([x['height'] for x in loc]) 
     return dict(depth=depth, height=height, inner=loc, txt=None) 

以上函数返回一个字典,我们需要这通过这本字典和情节的每个节点上的另一个功能:

def walk(loc, ax): 
    col, lw = 'DarkBlue', 2 
    x, y, inner, txt = map(loc.get, ['depth', 'height', 'inner', 'txt']) 
    if not inner: 
     ax.text(x, y, ' ' + txt, ha='left', va='center', size='large') 
     return y 
    else: 
     ys =[walk(t, ax) for t in inner] 
     for y1 in ys: 
      ax.plot([x, x+1], [y1, y1], color=col, linewidth=lw) 
     ax.plot([x, x], [min(ys), max(ys)], color=col, linewidth=lw) 
     return y 

location功能是在顶层通过传递count迭代器调用,返回一个词典,其包括所有必要的信息来绘制每个级别:

from itertools import count 
xs = ((('A','B'),('C','D')),'E',) 
loc = locate(xs, 0, count()) 

具有轴线沿着该字典被传递到walk功能:

fig = plt.figure(figsize=(2, 3)) 
ax = fig.add_axes([.05, .05, .9, .9])     
walk(loc, ax) 

plt.axis('off') 
xl, yl = ax.get_xlim(), ax.get_ylim() 
ax.set_xlim(xl[0] - .05, xl[1] + .05) 
ax.set_ylim(yl[0] - .05, yl[1] + .05) 

其结果将是:

tree1

另一个例子:

xs = ((('A','B','C','D'),('E'),('F1','F2'),'G'),(('H1','H2'),('I','J','K'),'L')) 

tree2

1

使用SciPy的的cluster.hierarchy.dendrogram

import re 
import numpy as np 
import matplotlib.pyplot as plt 
import scipy.cluster.hierarchy as hier 
import scipy.spatial.distance as dist 
import itertools as IT 

def parse_nested(text, left=r'[(]', right=r'[)]', sep=r','): 
    """ http://stackoverflow.com/a/17141899/190597 (falsetru) """ 
    pat = r'({}|{}|{})'.format(left, right, sep) 
    tokens = re.split(pat, text)  
    stack = [[]] 
    for x in tokens: 
     if not x: continue 
     if re.match(sep, x): continue 
     if re.match(left, x): 
      stack[-1].append([]) 
      stack.append(stack[-1][-1]) 
     elif re.match(right, x): 
      stack.pop() 
      if not stack: 
       raise ValueError('error: opening bracket is missing') 
     else: 
      stack[-1].append(x) 
    if len(stack) > 1: 
     print(stack) 
     raise ValueError('error: closing bracket is missing') 
    return stack.pop() 

def place_points(datalist, x=IT.count(), y=1): 
    retval = [] 
    for item in datalist: 
     if isinstance(item, list): 
      next(x) 
      retval.extend(place_points(item, x=x, y=y*2.5)) 
     else: 
      retval.append([item, (next(x), y)]) 
    return retval 

# data = '(((A,B,G),(C,D,F)),(E,(H,I,J,(K,L,M,N))))' 
data = '((A,B),(C,D),E)' 
labels, points = zip(*place_points(parse_nested(data))) 
d = dist.pdist(points) 
linkage_matrix = hier.linkage(d) 
P = hier.dendrogram(linkage_matrix, labels=labels) 
plt.show() 

enter image description here

相关问题