Building unique comma-delimited list?

R

Roy Smith

I've got a silly little problem that I'm solving in C++, but I got to
thinking about how much easier it would be in Python. Here's the
problem:

You've got a list of words (actually, they're found by searching a
data structure on the fly, but for now let's assume you've got them as
a list). You need to create a comma-delimited list of these words.
There might be duplicates in the original list, which you want to
eliminate in the final list. You don't care what order they're in,
except that there is a distinguised word which must come first if it
appears at all.

Some examples ("foo" is the distinguised word):

["foo"] => "foo"
["foo", "bar"] => "foo, bar"
["bar", "foo"] => "foo, bar"
["bar", "foo", "foo", "baz", "bar"] => "foo, bar, baz" or "foo, baz, bar"

The best I've come up with is the following. Can anybody think of a
simplier way?

--------------------
words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]

# Eliminate the duplicates; probably use set() in Python 2.4
d = dict()
for w in words:
d[w] = w

if d.has_key ("foo"):
newWords = ["foo"]
del (d["foo"])
else:
newWords = []

for w in d.keys():
newWords.append (w)

s = ', '.join (newWords)
print s
--------------------
 
?

=?iso-8859-15?q?Berthold_H=F6llmann?=

I've got a silly little problem that I'm solving in C++, but I got to
thinking about how much easier it would be in Python. Here's the
problem:

You've got a list of words (actually, they're found by searching a
data structure on the fly, but for now let's assume you've got them as
a list). You need to create a comma-delimited list of these words.
There might be duplicates in the original list, which you want to
eliminate in the final list. You don't care what order they're in,
except that there is a distinguised word which must come first if it
appears at all.

Some examples ("foo" is the distinguised word):

["foo"] => "foo"
["foo", "bar"] => "foo, bar"
["bar", "foo"] => "foo, bar"
["bar", "foo", "foo", "baz", "bar"] => "foo, bar, baz" or "foo, baz, bar"

The best I've come up with is the following. Can anybody think of a
simplier way?
....

How about:

..>>> words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
..>>> ', '.join(dict( ( (w,w) for w in words ) ).keys())
'baz, foo, bar'
..>>> words = ["foo",]
..>>> ', '.join(dict( ( (w,w) for w in words ) ).keys())
'foo'

or with Python 2.3 or higher:

..>>> import sets
..>>> words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
..>>> ', '.join(sets.Set(words))
'baz, foo, bar'
..>>> words = ["foo",]
..>>> ', '.join(sets.Set(words))
'foo'


Kind regards
Berthold
 
M

Mark McEahern

Roy said:
You've got a list of words (actually, they're found by searching a
data structure on the fly, but for now let's assume you've got them as
a list). You need to create a comma-delimited list of these words.
There might be duplicates in the original list, which you want to
eliminate in the final list. You don't care what order they're in,
except that there is a distinguised word which must come first if it
appears at all.

Some examples ("foo" is the distinguised word):

["foo"] => "foo"
["foo", "bar"] => "foo, bar"
["bar", "foo"] => "foo, bar"
["bar", "foo", "foo", "baz", "bar"] => "foo, bar, baz" or "foo, baz, bar"

The best I've come up with is the following. Can anybody think of a
simplier way?
Who knows whether this is "simpler", but it does demonstrate that you
can customize the sort of a list:

#!/usr/bin/env python

def makesorter(first):
"""Return a sort function that sorts first to the top."""
def sorter(x, y):
if x == first:
return -1
elif y == first:
return 1
else:
return 0
return sorter

words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
first = 'foo'
sorter = makesorter(first)
unique = {}
for word in words:
unique[word] = word
keys = unique.keys()
keys.sort(sorter)
print ', '.join(keys)
 
S

Scott David Daniels

How about (for 2.4 or 2.3 using "from collections import Set as set":

def combine(source, special='foo'):
parts = set(source)
if special in parts:
return ', '.join([special] + list(parts - set([special])))
return ', '.join(parts)

--Scott David Daniels
(e-mail address removed)
 
D

Duncan Booth

Roy said:
The best I've come up with is the following. Can anybody think of a
simplier way?

--------------------
words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]

# Eliminate the duplicates; probably use set() in Python 2.4
d = dict()
for w in words:
d[w] = w

if d.has_key ("foo"):
newWords = ["foo"]
del (d["foo"])
else:
newWords = []

for w in d.keys():
newWords.append (w)

s = ', '.join (newWords)
print s

You need to make the dictionary and list types work harder for you. They
have a variety of methods you might find useful.
words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
distinguished = ["foo"]
d = dict.fromkeys(words, True)
newwords = [ w for w in distinguished if d.pop(w, False) ]
newwords.extend(d.keys())
newwords ['foo', 'baz', 'bar']
 
B

Bengt Richter

I've got a silly little problem that I'm solving in C++, but I got to
thinking about how much easier it would be in Python. Here's the
problem:

You've got a list of words (actually, they're found by searching a
data structure on the fly, but for now let's assume you've got them as
a list). You need to create a comma-delimited list of these words.
There might be duplicates in the original list, which you want to
eliminate in the final list. You don't care what order they're in,
except that there is a distinguised word which must come first if it
appears at all.

Some examples ("foo" is the distinguised word):

["foo"] => "foo"
["foo", "bar"] => "foo, bar"
["bar", "foo"] => "foo, bar"
["bar", "foo", "foo", "baz", "bar"] => "foo, bar, baz" or "foo, baz, bar"

The best I've come up with is the following. Can anybody think of a
simplier way?
(Not tested beyond what you see ;-)
python 2.4:
>>> words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
>>> w2 = list(t[1] for t in sorted((w!='foo', w) for w in set(words)))
>>> w2
['foo', 'bar', 'baz']

Gets you a sort in the bargain ;-)
Yup, but 2.3 can be a one-liner too:
>>> words = ["foo", "bar", "baz", "foo", "bar", "foo", "baz"]
>>> w2 = ('foo' in words and ['foo'] or []) + [w for w in dict(zip(words,words)) if w!='foo']
>>> w2
['foo', 'baz', 'bar']

Not sorted, but foo is out front.
d = dict()
for w in words:
d[w] = w

if d.has_key ("foo"):
newWords = ["foo"]
del (d["foo"])
else:
newWords = []

for w in d.keys():
newWords.append (w)

s = ', '.join (newWords)
print s
--------------------

Regards,
Bengt Richter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top