How do I extract part of a tuple that's duplic

2019-08-13 02:10发布

问题:

I'm pretty new to Python and Qgis, right now I'm just running scripts but I my end-goal is to create a plugin.

Here's the part of the code I'm having problems with:

import math

layer = qgis.utils.iface.activeLayer()
iter = layer.getFeatures()
dict = {}

#iterate over features
for feature in iter:
    #print feature.id()
    geom = feature.geometry()
    coord = geom.asPolyline()
    points=geom.asPolyline()
#get Endpoints
    first = points[0]
    last = points[-1]

#Assemble Features
dict[feature.id() ]= [first, last]

print dict

This is my result : {0L: [(355277,6.68901e+06), (355385,6.68906e+06)], 1L: [(355238,6.68909e+06), (355340,6.68915e+06)], 2L: [(355340,6.68915e+06), (355452,6.68921e+06)], 3L: [(355340,6.68915e+06), (355364,6.6891e+06)], 4L: [(355364,6.6891e+06), (355385,6.68906e+06)], 5L: [(355261,6.68905e+06), (355364,6.6891e+06)], 6L: [(355364,6.6891e+06), (355481,6.68916e+06)], 7L: [(355385,6.68906e+06), (355501,6.68912e+06)]}

As you can see, many of the lines have a common endpoint:(355385,6.68906e+06) is shared by 7L, 4L and 0L for example.

I would like to create a new dictionary, fetching the shared points as a key, and having the second points as value.

eg : {(355385,6.68906e+06):[(355277,6.68901e+06), (355364,6.6891e+06), (355501,6.68912e+06)]}

I have been looking though list comprehension tutorials, but without much success: most people are looking to delete the duplicates, whereas I would like use them as keys (with unique IDs). Am I correct in thinking set() would still be useful?

I would be very grateful for any help, thanks in advance.

回答1:

Maybe this is what you need?

dictionary = {}
for i in dict:
    for j in dict:
        c = set(dict[i]).intersection(set(dict[j]))
        if len(c) == 1:
            # ok, so now we know, that exactly one tuple exists in both
            # sets at the same time, but this one will be the key to new dictionary
            # we need the second tuple from the set to become value for this new key
            # so we can subtract the key-tuple from set to get the other tuple
            d = set(dict[i]).difference(c)
            # Now we need to get tuple back from the set
            # by doing list(c) we get list
            # and our tuple is the first element in the list, thus list(c)[0]
            c = list(c)[0]
            dictionary[c] = list(d)[0]
        else: pass

This code attaches only one tuple to the key in dictionary. If you want multiple values for each key, you can modify it so that each key would have a list of values, this can be done by simply modifying:

# some_value cannot be a set, it can be obtained with c = list(c)[0]
key = some_value
dictionary.setdefault(key, [])
dictionary[key].append(value)

So, the correct answer would be:

dictionary = {}
for i in a:
        for j in a:
            c = set(a[i]).intersection(set(a[j]))
            if len(c) == 1:
                d = set(a[i]).difference(c)
                c = list(c)[0]
                value = list(d)[0]
                if c in dictionary and value not in dictionary[c]:
                    dictionary[c].append(value)
                elif c not in dictionary:
                    dictionary.setdefault(c, [])
                    dictionary[c].append(value)

            else: pass


回答2:

See this code :

dict={0L: [(355277,6.68901e+06), (355385,6.68906e+06)], 1L: [(355238,6.68909e+06), (355340,6.68915e+06)], 2L: [(355340,6.68915e+06), (355452,6.68921e+06)], 3L: [(355340,6.68915e+06), (355364,6.6891e+06)], 4L: [(355364,6.6891e+06), (355385,6.68906e+06)], 5L: [(355261,6.68905e+06), (355364,6.6891e+06)], 6L: [(355364,6.6891e+06), (355481,6.68916e+06)], 7L: [(355385,6.68906e+06), (355501,6.68912e+06)]}
dictionary = {}
list=[]
for item in dict :
   list.append(dict[0])
   list.append(dict[1])

b = []

[b.append(x) for c in list for x in c if x not in b]
print b # or set(b)
res={}

for elm in b :
   lst=[]
   for item in dict :
       if dict[item][0] == elm :
           lst.append(dict[item][1])
       elif dict[item][1] == elm :
           lst.append(dict[item][0])
   res[elm]=lst

print res