views:

90

answers:

4

I have a list of tuples of the form (a,b,c,d) and I want to copy only those tuples with unique values of 'a' to a new list. I'm very new to python.

Current idea that isn't working:

for (x) in list:
   a,b,c,d=(x)
   if list.count(a)==1:
      newlist.append(x)
+2  A: 
values = {}

for t in tups:
  a,b,c,d = t
  if a not in values:
    values[a] = (1, t)
  else:
    count, tup = values[a]
    values[a] = (count+1, t)

unique_tups = map(lambda v: v[1],
                  filter(lambda k: k[0] == 1, values.values()))

I am using a dictionary to store a values and the tuples that have that a value. The value at that key is a tuple of (count, tuple) where count is the number of times that a has been seen.

At the end, I filter the values dictionary for only those a values where the count is 1, i.e. they are unique. Then I map that list to return only those tuples, since the count value will be 1.

Now, unique_tups is a list of all those tuples with unique a's.

Updated after receiving feedback from commenters, thanks!

Jesse Dhillon
This doesn't really make a list, which the OP asked for. It also will lose track of the order (OP doesn't say if that is problem) and it doesn't just put the entries where "a" is unique, but will just pick the first entry for each value of "a"
Mattias Nilsson
Thanks for the feedback, I've updated it to try to make it correct.
Jesse Dhillon
+3  A: 

If you don't want to add any of the tuples that have duplicate a values (as opposed to adding the first occurrence of a given a, but none of the later ones):

seen = {}
for x in your_list:
    a,b,c,d = x
    seen.setdefault(a, []).append(x)

newlist = []
for a,x_vals in seen.iteritems():
    if len(x_vals) == 1:
        newlist.append(x_vals[0])
Amber
Thanks, this is perfect.
coup
A: 

you could indeed sort the list and then iterate over it:

xs = [(1,2,3,4), (5, 2, 3, 4), (2, 3, 3, 3), (1, 5, 2, 3)]
newList = []
xs.sort()
lastX = None
for x in xs:
  if lastX:
    if lastX[0] == x[0]:
      lastX = None
    else:
      newList.append(lastX)
      lastX = x
if lastX:
  newList.append(lastX)
nazgul
This also works well! thanks!
coup
Hang on, wouldn't this keep this keep the first tuple with a given value for 'a' and ignore the rest? For example, if the first few tuples are [(125, b, c, d) (125, b, c, d) (127, b, c, d) (127, b, c, d) (128, b, c, d) (129, b, c, d)], then this iteration would append the first tuple but not the second, and the third tuple but not the fourth, when none of those four have unique values for 'a'.
coup
Ok, I misunderstood your objective. The updated code will look at last element and only if it differs from current one on [0] (and there were no others with that [0]), it will add it to the output list.
nazgul
+2  A: 

You could use a set to keep track of the duplicates:

seen_a = set()
for x in list:
    a, b, c, d = x
    if a not in seen_a:
        newlist.append(x)
        seen_a.add(x)
Ferdinand Beyer
This, like Jesses suggestion, will take the first entry for each value of "a", not just the ones where "a" i unique.
Mattias Nilsson