Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dictionary 用Pythonic方法浏览自指词典_Dictionary_Python 3.x_Python - Fatal编程技术网

Dictionary 用Pythonic方法浏览自指词典

Dictionary 用Pythonic方法浏览自指词典,dictionary,python-3.x,python,Dictionary,Python 3.x,Python,我有一个字典,其中条目值可以通过键引用另一个条目,最终在当前值没有条目或遇到“-”时结束。此数据结构的目标是为每个条目找到父项,并将“-”转换为“无”。例如: d={'1':'-','0':'6','3':'1','2':'3','4':'5','6':'9'} “1”是一个映射到“-”的根,因此它应该不会产生任何结果 “0”的父项为“6”,而该父项为“9”,因此应生成“9” “3”有一个“1”的父项,它映射到“-”,因此它应该不会产生任何结果 “2”的父项为“3”,而“1”的父项映射到“-

我有一个字典,其中条目值可以通过键引用另一个条目,最终在当前值没有条目或遇到“-”时结束。此数据结构的目标是为每个条目找到父项,并将“-”转换为“无”。例如:

d={'1':'-','0':'6','3':'1','2':'3','4':'5','6':'9'}
  • “1”是一个映射到“-”的根,因此它应该不会产生任何结果
  • “0”的父项为“6”,而该父项为“9”,因此应生成“9”
  • “3”有一个“1”的父项,它映射到“-”,因此它应该不会产生任何结果
  • “2”的父项为“3”,而“1”的父项映射到“-”,因此它应该不会产生任何结果
  • “4”应保留在“5”的父项中
  • “6”应保留在“9”的父项中
我详细的解决方案如下:

d={'1':'-','0':'6','3':'1','2':'3','4':'5','6':'9'}
印刷品(d)
对于dis,在d.items()中表示:
如果rep==“-”:
d[dis]=无
持续
在d中代表时:
rep=d[rep]
如果rep==“-”:
d[dis]=无
打破
其他:
d[dis]=rep
印刷品(d)
输出为:

{'1':'-','0':'6','3':'1','2':'3','4':'5','6':'9'}
{'1':无,'0':'9','3':无,'2':无,'4':'5','6':'9'}
结果是正确的。“1”元素没有父元素,“2”/“3”元素指向“1”。他们也应该没有父母


使用Python3+有没有更简洁的Python方法来实现这一点?

您可以定义这样的函数

def recursive_get(d, k):
    v = d[k]
    if v == '-':
        v = d[k] = None
    elif v in d:
        v = d[k] = recursive_get(d, v)
    return v
当您使用
recursive\u get
访问键时,它将在遍历时修改值。 这意味着您不必浪费时间打包从不需要的分支

>>> d = {'1': '-', '3': '1', '2': '3'}
>>> recursive_get(d, '3')
>>> d
{'1': None, '3': None, '2': '3'}         # didn't need to visit '2'

>>> d = {'1': '-', '3': '1', '2': '3'}
>>> recursive_get(d, '2')
>>> d
{'1': None, '3': None, '2': None}
如果您想强制
d
进入最终状态,只需循环所有键即可

for k in d:
    recursive_get(d, k)
要“漫游”字典,只需循环查找,直到没有:

>>> def walk(d, val):
        while val in d:
            val = d[val]
        return None if val == '-' else val

>>> d = {'1': '-', '0': '6', '3': '1', '2': '3', '4': '5', '6': '9'}
>>> print {k: walk(d, k) for k in d}
{'1': None, '0': '9', '3': None, '2': None, '4': '5', '6': '9'}
我想发布一些到目前为止关于这三种方法的分析统计数据:

运行原始程序解决方案。
在0.221秒内调用5个函数
订购人:标准名称
ncalls tottime percall cumtime percall文件名:lineno(函数)
1    0.000    0.000    0.221    0.221 :1()
1 0.221 0.221 0.221 0.221测试。py:12(详细)
1 0.000 0.000 0.221 0.221{内置方法exec}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
1 0.000 0.000 0.000 0.000{“dict”对象的方法“items”}
885213
运行递归解决方案。
994022函数调用只需1.252秒
订购人:标准名称
ncalls tottime percall cumtime percall文件名:lineno(函数)
1    0.000    0.000    1.252    1.252 :1()
994018 0.632 0.000 0.632 0.000测试。py:27(递归)
1 0.620 0.620 1.252 1.252测试。py:35(do_递归)
1 0.000 0.000 1.252 1.252{内置方法exec}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
885213
运行dict理解解决方案。
994023函数调用只需1.665秒
订购人:标准名称
ncalls tottime percall cumtime percall文件名:lineno(函数)
1    0.059    0.059    1.665    1.665 :1()
994018 0.683 0.000 0.683 0.000测试。py:40(步行)
1 0.000 0.000 1.606 1.606测试。py:45(听写理解)
1 0.923 0.923 1.606 1.606试验。py:46()
1 0.000 0.000 1.665 1.665{内置方法exec}
1 0.000 0.000 0.000 0.000{方法'disable'的''lsprof.Profiler'对象}
885213
下面是运行这三种方法的代码:

导入cProfile
导入csv
导入gzip
def gzip_to_text(gzip_文件,encoding=“ascii”):
使用gzip.open(gzip_文件)作为gzf:
对于gzf中的行:
产量str(行,编码)
详细定义(d):
对于dis,在d.items()中表示:
如果rep==“-”:
d[dis]=无
持续
在d中代表时:
rep=d[rep]
如果rep==“-”:
d[dis]=无
打破
其他:
d[dis]=rep
返回d
def递归(d,k):
v=d[k]
如果v=='-':
v=d[k]=无
以利夫五世为例:
v=d[k]=递归(d,v)
返回v
def do_递归(d):
对于d中的k:
递归(d,k)
返回d
def步行(d,val):
而val在d中:
val=d[val]
如果val='-'则返回None,否则返回val
def dict_理解(d):
返回{k:d中k的行走(d,k)}
#从url提取的公共数据集:ftp://ftp.ncbi.nih.gov/gene/DATA/gene_history.gz
csvr=csv.reader(gzip_to_text(“gene_history.gz”),分隔符=“\t”,引号=“\”)
d={rec[2]。strip():rec[1]。如果csvr.line_num>1}
打印(“运行原始程序解决方案”)
cProfile.run('d=verbose(d)'
c=0
对于d.项()中的k,v:
c+=(如果v不是其他0,则为1)
印刷品(c)
打印(“运行递归解决方案”)
cProfile.run('d=do\u递归(d)'
c=0
对于d.项()中的k,v:
c+=(如果v不是其他0,则为1)
印刷品(c)
打印(“运行dict理解解决方案”)
cProfile.run('d=听写理解(d)'
c=0
对于d.项()中的k,v:
c+=(如果v不是其他0,则为1)
印刷品(c)

你能澄清你想要实现什么吗?正如@ch3ka所说的。你的输入/输出也与文本不匹配。要从给定的输入中获得给定的输出,你只需执行
{k:None for k in d}
,但我怀疑这是你想要的。我已经更详细地更新了原始问题并更正了代码。是
{'1':None,'3':None,'2':None}
正确的输出?你能举个例子,说明不是所有的值都是
None
?如果你总是沿着链接一直到
-
(你用
None
)为止,那么你总是会有
None
的值,对吗?有一个计数器检查吗