Re: Python sets which support multiple same elements

2011-05-20 Thread Shunichi Wakabayashi
> Many times when I am writing some program in python, I notice that I
> could transform my list into set, then use the set methods like union,
> intersection, set equality etc. , and it will solve my problem easily.
> But then I realize that if I transform my list into set, it will
> remove duplicates of elements in the list and so I will lose
> information from my original list.
> 
> For example, I was writing a program to detect whether two strings are
> anagrams of each other. I had to write it like this:
> 
> def isAnagram(w1, w2):
>   w2=list(w2)
>   for c in w1:
> if c not in w2:
>   return False
> else:
>   w2.remove(c)
>   return True
> 
> But if there was a data structure in python which supported duplicate
> elements(lets call it dset), then I could just write:
> 
> def inAnagram(w1,w2):
>   return dset(w1)==dset(w2)
> 
> Example of some dset methods:
> {1,2,3,3} intersection {4,1,2,3,3,3}  == {1,2,3,3}
> {1,2,3,3} union {4,1,2,3,3,3} == {1,2,3,3,3,4}
> {4,1,2,3,3,3} difference {1,2,3,3} == {4,3}
> 
> Do you think that it would be a good idea to add this kind of data
> structure to python? Or did I overlook some other easy way to solve
> this kind of problems?

I think collections.Counter object may be useful for your purpose.

http://docs.python.org/py3k/library/collections.html#collections.Counter
-- 
http://mail.python.org/mailman/listinfo/python-list


Writing multiple files with with-context

2011-05-22 Thread Shunichi Wakabayashi
To write onto multiple files on the same time (a number of files are variable),
I'd like to code as follows, for example, IF I can do,

LIST_LEN = 4
with [ open('list_%d.txt' % i, 'w') for i in range(LIST_LEN) ] as fobjlist:
  for i in range(1000):
fobjlist[random.randrange(LIST_LEN)].write(str(i)+"\n")

or using a dict object,

DICT_KEYS = ('foo', 'bar', 'baz')
with { k: open('dict_%s.txt' % k, 'w') for k in DICT_KEYS } as fobjdict:
  for i in range(1000):
fobjdict[random.choice(DICT_KEYS)].write(str(i)+"\n")

However, list and dict don't has __exit__ method and so they cannot run.
One idea is using contextlib.nested(),

from contextlib import nested

with nested(*[open('list_%d.txt' % i, 'w') for i in range(LIST_LEN)]) as 
fobjlist:
  for i in range(1000):
fobjlist[random.randrange(LIST_LEN)].write(str(i)+"\n")

with nested(*[open('dict_%s.txt' % k, 'w') for k in DICT_KEYS]) as fobjlist:
  fobjdict = dict(zip(DICT_KEYS, fobjlist)) #convert list to dict
  for i in range(1000):
fobjdict[random.choice(DICT_KEYS)].write(str(i)+"\n")

On Python2.x, this is OK. but 3.x warns that nested() is deprecated.
Moreover, on using dict, it is required to convert list to dict.

Another idea is to make container classes having __exit__() myself.

class MyList(list):
  def __enter__(self):
return [ v.__enter__() for v in self ]
  def __exit__(self, exc_type, exc_value, traceback):
ret = False
for v in self:
  if v.__exit__(exc_type, exc_value, traceback):
ret = True
exc_type = exc_value = traceback = None
return ret

class MyDict(dict):
  def __enter__(self):
return { k: v.__enter__() for k, v in self.items() }
  def __exit__(self, exc_type, exc_value, traceback):
ret = False
for v in self.values():
  if v.__exit__(exc_type, exc_value, traceback):
ret = True
exc_type = exc_value = traceback = None
return ret

with MyList( open('list_%d.txt' % i, 'w') for i in range(LIST_LEN) ) as 
fobjlist:
  for i in range(1000):
fobjlist[random.randrange(LIST_LEN)].write(str(i)+"\n")

with MyDict( (k, open('dict_%s.txt' % k, 'w')) for k in DICT_KEYS ) as fobjdict:
  for i in range(1000):
fobjdict[random.choice(DICT_KEYS)].write(str(i)+"\n")

I think this is smarter a little than others,
but it cannot guaranteed to call __exit__() of members in containers
if members are changed during with-context.

So, do you have another, more smart and pythonic way?

Thanks
-- 
http://mail.python.org/mailman/listinfo/python-list