Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.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
Python 需要从其成员可能连接的集合列表中创建集合列表_Python_Api_Maya - Fatal编程技术网

Python 需要从其成员可能连接的集合列表中创建集合列表

Python 需要从其成员可能连接的集合列表中创建集合列表,python,api,maya,Python,Api,Maya,我在这里实时处理多边形数据,但问题很简单。 我有一个包含数千组多边形索引(整数)的庞大列表,我需要尽可能“快速”地将该列表简化为一组“连接”索引。 i、 e.任何包含整数的集合如果也在另一个集合中,则在结果中成为一个集合。我读过一些可能的解决方案,包括集合和图形等。我想要的是一个集合的最终列表,它具有任何程度的通用性 我在这里处理大量数据,但为了简单起见,这里有一些示例数据: setA = set([0,1,2]) setB = set([6,7,8,9]) setC = set([4,5,6]

我在这里实时处理多边形数据,但问题很简单。 我有一个包含数千组多边形索引(整数)的庞大列表,我需要尽可能“快速”地将该列表简化为一组“连接”索引。 i、 e.任何包含整数的集合如果也在另一个集合中,则在结果中成为一个集合。我读过一些可能的解决方案,包括集合和图形等。我想要的是一个集合的最终列表,它具有任何程度的通用性

我在这里处理大量数据,但为了简单起见,这里有一些示例数据:

setA = set([0,1,2])
setB = set([6,7,8,9])
setC = set([4,5,6])
setD = set([3,4,5,0])
setE = set([10,11,12])
setF = set([11,13,14,15])
setG = set([16,17,18,19])

listOfSets = [setA,setB,setC,setD,setE,setF,setG]
在这种情况下,我在寻找一个结果如下的列表,尽管排序与此无关:

连接面集合=[集合([0,1,2,3,4,5,6,7,8,9]),集合([10,11,12,13,14,15]),集合([16,17,18,19])]

我曾寻找过类似的解决方案,但在我的大量测试数据中,投票率最高的那个给出了错误的结果


这是一个联合查找问题

虽然我还没有使用它,但这段Python代码对我来说很不错


如果没有足够大的集合,很难判断性能,但下面是一些基本代码:

while True:
    merged_one = False
    supersets = [listOfSets[0]]

    for s in listOfSets[1:]:
        in_super_set = False
        for ss in supersets:
            if s & ss:
               ss |= s
               merged_one = True
               in_super_set = True
               break

        if not in_super_set:
            supersets.append(s)

    print supersets
    if not merged_one:
        break

    listOfSets = supersets       
这将在提供的数据上进行3次迭代。输出如下:

[set([0, 1, 2, 3, 4, 5]), set([4, 5, 6, 7, 8, 9]), set([10, 11, 12, 13, 14, 15]), set([16, 17, 18, 19])]
[set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), set([10, 11, 12, 13, 14, 15]), set([16, 17, 18, 19])]
[set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), set([10, 11, 12, 13, 14, 15]), set([16, 17, 18, 19])]

原谅那些乱七八糟的大写字母(自动更正…):


所以。。我想我明白了。一团糟,但我明白了。以下是我所做的:

def connected_valid(li):
    for i, l in enumerate(li):
        for j, k in enumerate(li):
            if i != j and contains(l,k):
                return False
    return True

def contains(set1, set2):
    for s in set1:
        if s in set2:
            return True
    return False

def combine(set1, set2):
    set2 |= set1
    return set2

def connect_sets(li):
    while not connected_valid(li):
        s1 = li.pop(0)
        s2 = li[0]
        if contains(s1, s2):
            li[0] = combine(s1,s2)
        else:
            li.append(s1)
    return li
然后在主函数中,您将执行以下操作:

setA = set([0,1,2])
setB = set([6,7,8,9])
setC = set([4,5,6])
setD = set([3,4,5,0])
setE = set([10,11,12])
setF = set([11,13,14,15])
setG = set([16,17,18,19])

connected_sets = connect_sets([setA,setB,setC,setD,setE,setF,setG,])
运行它之后,我得到了以下输出

print connected_sets
[set([0,1,2,3,4,5,6,7,8,9]), set([10,11,12,13,14,15]), set([16,17,18,19])]
希望这就是你要找的

编辑:添加代码以随机生成集合:

# Creates a list of 4000 sets with a random number of values ranging from 0 to 20000
sets = []
ma = 0
mi = 21000
for x in range(4000):
    rand_num = sample(range(20),1)[0]
    tmp_set_li = sample(range(20000), rand_num)
    sets.append(set(tmp_set_li))

如果你真的愿意,最后三行可以压缩成一行。

我尝试做一些不同的事情:这个算法对每个集合循环一次,对每个元素循环一次:

# Our test sets
setA = set([0,1,2])
setB = set([6,7,8,9])
setC = set([4,5,6])
setD = set([3,4,5,0])
setE = set([10,11,12])
setF = set([11,13,14,15])
setG = set([16,17,18,19])

list_of_sets = [setA,setB,setC,setD,setE,setF,setG]

# We will use a map to store our new merged sets.
# This map will work as an reference abstraction, so it will
# map set ids to the set or to other set id.
# This map may have an indirection level greater than 1
merged_sets = {}

# We will also use a map between indexes and set ids.
index_to_id = {}

# Given a set id, returns an equivalent set id that refers directly
# to a set in the merged_sets map
def resolve_id(id):
    if not isinstance(id, (int, long)):
        return None
    while isinstance(merged_sets[id], (int, long)):
        id = merged_sets[id]
    return id


# Points the informed set to the destination id
def link_id(id_source, id_destination):
    point_to = merged_sets[id_source]
    merged_sets[id_source] = id_destination
    if isinstance(point_to, (int, long)):
        link_id(point_to, id_destination)


empty_set_found = False
# For each set
for current_set_id, current_set in enumerate(list_of_sets):
    if len(current_set) == 0 and empty_set_found:
        continue
    if len(current_set) == 0:
        empty_set_found = True
    # Create a set id for the set and place it on the merged sets map
    merged_sets[current_set_id] = current_set
    # For each index in the current set
    possibly_merged_current_set = current_set
    for index in current_set:
        # See if the index is free, i.e., has not been assigned to any set id
        if index not in index_to_id:
            # If it is free, then assign the set id to the index
            index_to_id[index] = current_set_id
            # ... and then go to the next index
        else:
            # If it is not free, then we may need to merge the sets
            # Find out to which set we need to merge the current one,
            # ... dereferencing if necessary
            id_to_merge = resolve_id(index_to_id[index])
            # First we check to see if the assignment is to the current set or not
            if id_to_merge == resolve_id(merged_sets[current_set_id]):
                continue
            # Merge the current set to the one found
            print 'Merging %d with %d' % (current_set_id, id_to_merge)
            merged_sets[id_to_merge] |= possibly_merged_current_set
            possibly_merged_current_set = merged_sets[id_to_merge]
            # Map the current set id to the set id of the merged set
            link_id(current_set_id, id_to_merge)
# Return all the sets in the merged sets map (ignore the references)
print [x for x in merged_sets.itervalues() if not isinstance(x, (int, long))]
它打印:

Merging 2 with 1
Merging 3 with 0
Merging 3 with 1
Merging 5 with 4
[set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), set([10, 11, 12, 13, 14, 15]), set([16, 17, 18, 19])]

在小型示例数据lamback上,这看起来很有希望。明天我将在我的插件中试一试,看看它如何公平。干杯,好好享受。谢谢你。如果我有15个代表,我会投票支持你。如果你追求速度,你会想删除函数调用,因为它们是众所周知的减速。在
循环的每次迭代中搜索一个非连接集也需要很长时间,最好在迭代时跟踪它并保留一个标志。Lamback的方法似乎很简洁,对我很有效,所以除非有更快的解决方案,否则我将使用这个答案。在我的4064组列表中,它只需要不到0.01秒,所以这对我来说很好。我很好奇你是如何使用lambaack的方法在0.01秒内完成任务的。我已经运行了2分钟,但它还没有完成。你最小/最大的开始集是什么?我使用的是一个随机生成的4000套的列表。并不是说我在敲lambaack或其他什么(我的答案可能需要更长的时间),我只是想知道你用了什么。@Bryce Siedschlaw:你创建集合的代码是什么?我有兴趣尝试一组更大的集合。@lamback我在答案中添加了代码来生成随机集合列表。我用timeit运行每个答案——最快的是lamback 0.03(11个函数调用),其次是Thiago 0.07(50个调用)和Bryce 0.1(69个调用)。这个算法只运行一次,在许多情况下都会给出错误的答案。例如,对于输入[(1,2)、(2,3)、(3,4)],它将错误地回答[(1,2,3)、(1,2,3,4)、(2,3,4)]
Merging 2 with 1
Merging 3 with 0
Merging 3 with 1
Merging 5 with 4
[set([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), set([10, 11, 12, 13, 14, 15]), set([16, 17, 18, 19])]