如何在Python中执行以下有序子集元素测试?
我有一个字典(称为dict),它的键是表示特征名称的字符串,其值是表示每个特征计数的浮点数 下面是我的字典(dict)的一个例子: {'11268-238-1028':2.0,'1028':10.0,'10295':2.0,'1781':2.0,'11268-238':3.0,'6967-167':1.0,'9742-232-788':1.0,'8542':4.0,'238-1028':5.0,'1028-122':1.0} 在本例中,“10295”被视为一度特征,“6967-167”被视为二度特征,“9742-232-788”被视为三度特征。如果我们有“x-x-x-x-x-x-x-x”,那么它将是一个七度特征。换句话说,对于任何n阶特征,该特征具有(n-1)个破折号('-') “11268-238-1028”:2.0表示3度特征“11268-238-1028”的计数为2。然后我们看到'11268-238':3.0,这意味着'11268-238'出现了3次。然而,这是一些重复计数问题,因为在“11268-238”的3次出现中,有2次实际上是由于“11268-238-1028”的出现。因此,我们希望将“11268-238”的计数更改为其实际计数,即3-2=1 类似地,“238-1028”的实际计数不是5,因为“238-1028”是“11268-238-1028”的一部分,“11268-238-1028”的计数为2。因此,“238-1028”的实际计数应该是(5-2=3) 另一个例子是功能“1028”,其实际计数不应为10“1028”是三度特征“11268-238-1028”的一部分,其计数为2“1028”也是2度特征“238-1028”的一部分,其计数为51028'也是计数为1的2度特征“1028-122”的一部分。因此,1度特征“1028”的实际计数应为(10-2-5-1=2) 我应该使用什么样的算法来解决这个问题 我考虑将每个关键点转换为一组由破折号分割的1度特征,然后针对每个特征集,对所有其他长度更高的特征集进行子集成员资格测试。但是,set存储无序元素,但我关心顺序。例如,转换为集合的要素“11268-238-1028”将是(['11268',238',1028']);转换为set的另一个功能“11268-1028”是(['11268','1028'])。如果我对这两个特征集进行子集测试,我会得出结论(['11268','1028'])是(['11268','238','1028'])的子集。然而,特征“11268-1028”不是特征“11268-238-1028”的子集,因为在“11268”和“1028”之间,还有另一件事“238”,即顺序应该是重要的 那我怎么解决这个问题呢如何在Python中执行以下有序子集元素测试?,python,python-2.7,dictionary,set,subset,Python,Python 2.7,Dictionary,Set,Subset,我有一个字典(称为dict),它的键是表示特征名称的字符串,其值是表示每个特征计数的浮点数 下面是我的字典(dict)的一个例子: {'11268-238-1028':2.0,'1028':10.0,'10295':2.0,'1781':2.0,'11268-238':3.0,'6967-167':1.0,'9742-232-788':1.0,'8542':4.0,'238-1028':5.0,'1028-122':1.0} 在本例中,“10295”被视为一度特征,“6967-167”被视为二度
非常感谢 将您的问题分解为更小、更不复杂的问题 首先,让我们编写一个帮助函数来实际调整数据字典
# this assumes we have one big feature (ie 3) and several smaller features(ie 2&1)
def adjust_data(big_feature,smaller_features,data):
for feature in smaller_features:
if feature.count("-") == big_feature.count("-"):
continue # skip any features that are the same size as our target
#3 cases for a sub feature it starts with ends with or is contained
# we use delimiters to eliminate partial matches
does_start = big_feature.startswith(feature+"-")
does_end = bigfeature.endswith("-"+feature)
does_contain = "-"+feature+"-" in big_feature
if does_start or does_end or does_contain :
# one of our cases match so this is a sub feature of our big feature
data[feature] -= data[big_feature]
现在,在处理此问题之前,我们需要组织数据,以便对其进行适当排序
sorted_keys = sorted(my_data_dict.keys(),
key=lambda key:key.count("-"),
reversed=True) #we want bigger features on top
现在只需浏览我们的排序数据列表
for i,key in enumerate(sorted_keys,1):
adjust_data(key,sorted_keys[i:],my_data_dict)
这只是蛮力,所以速度不会那么快,但可以完成任务在创建dict时防止重复计算应该比以后撤销它容易得多 但假设无法重新创建dict。这里有一个解决方案。它并不假设对于每个高阶特征,每个阶都保证有一个低阶对应项(即,对于特征A1-A2-…-An,您可能会缺少A1、A1-A2等中的任何一个,直到A1-A2-…-An-1)。如果这个假设真的成立,那么可以简化一些
try except
def undo_double_counting(d):
sorted_features = sorted(d, key=lambda f: f.count('-'), reverse=True)
for f in sorted_features:
if '-' not in f:
return d
feature_below, _ = f.rsplit('-', 1)
while True:
try:
d[feature_below] -= d[f]
except KeyError:
# if the feature one degree below isn't actually in d,
# we keep trying lower degrees until we know that we
# can't go lower any more (by hitting ValueError)
try:
feature_below, _ = feature_below.rsplit('-', 1)
except ValueError:
break
else:
break
# if there are no degree-1 features in d, return here
return d
在您的数据上尝试它(顺便说一句,为什么是float,而不是int?)
你试过什么了吗?不要转换为set,而是像l='11268-238-1028'和l.split('-')那样拆分成列表,然后连续比较你甚至不需要这样做…或者检查它是否是一个子字符串
{'1028': 9.0,
'1028-122': 1.0,
'10295': 2.0,
'11268-238': 1.0,
'11268-238-1028': 2.0,
'1781': 2.0,
'238-1028': 5.0,
'6967-167': 1.0,
'8542': 4.0,
'9742-232-788': 1.0}