Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #105389 > unrolled thread

Convert list to another form but providing same information

Started byMaurice <mauricioliveiraguarda@gmail.com>
First post2016-03-21 11:26 -0700
Last post2016-03-22 21:49 +1100
Articles 15 — 10 participants

Back to article view | Back to comp.lang.python


Contents

  Convert list to another form but providing same information Maurice <mauricioliveiraguarda@gmail.com> - 2016-03-21 11:26 -0700
    Re: Convert list to another form but providing same information Maurice <mauricioliveiraguarda@gmail.com> - 2016-03-21 11:30 -0700
      Re: Convert list to another form but providing same information Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-21 19:24 +0000
      Re: Convert list to another form but providing same information anantguptadbl@gmail.com - 2016-03-22 07:23 -0700
    Re: Convert list to another form but providing same information Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-21 19:21 +0000
    Re: Convert list to another form but providing same information Peter Otten <__peter__@web.de> - 2016-03-21 20:22 +0100
    Re: Convert list to another form but providing same information Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-03-21 20:03 +0000
      Re: Convert list to another form but providing same information Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-21 14:12 -0600
        Re: Convert list to another form but providing same information Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-03-22 00:31 +0000
          Re: Convert list to another form but providing same information Chris Angelico <rosuav@gmail.com> - 2016-03-22 11:58 +1100
          Re: Convert list to another form but providing same information Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2016-03-22 15:34 +1100
      Re: Convert list to another form but providing same information Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-21 14:14 -0600
    Re: Convert list to another form but providing same information Steven D'Aprano <steve@pearwood.info> - 2016-03-22 11:13 +1100
    Re: Convert list to another form but providing same information Paul Rubin <no.email@nospam.invalid> - 2016-03-21 18:35 -0700
      Re: Convert list to another form but providing same information Steven D'Aprano <steve@pearwood.info> - 2016-03-22 21:49 +1100

#105389 — Convert list to another form but providing same information

FromMaurice <mauricioliveiraguarda@gmail.com>
Date2016-03-21 11:26 -0700
SubjectConvert list to another form but providing same information
Message-ID<1010f2cb-21f9-495b-8af4-03ad209b4c1e@googlegroups.com>
Hello, hope everything is okay. I think someone might have dealt with a similar issue I'm having.

Basically I wanna do the following:

I have a list such [6,19,19,21,21,21] (FYI this is the item of a certain key in the dictionary)

And I need to convert it to a list of 32 elements (meaning days of the month however first element ie index 0 or day zero has no meaning - keeping like that for simplicity's sake).
Therefore the resulting list should be:
[0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]

So the list index should tell how many occurrences of a certain day in the original list. 

My attempt:

weirdList = [[0]*32]*len(dict_days) #list's length should be how many keys in the dict.

counter = 0
k = 0
for key in dict_days.keys():
    for i in range(1,32):
        if i in dict_days[key]:
            counter = dict_days[key].count(i)
            weirdList[k][i] = counter
    dict_days[key] = weirdList[k]
    k+=1

However it does not work. weirdList seems to be always the same? 

Thanks in advance.

[toc] | [next] | [standalone]


#105390

FromMaurice <mauricioliveiraguarda@gmail.com>
Date2016-03-21 11:30 -0700
Message-ID<eb002b45-6b6b-422c-8a9b-ee36c95109ca@googlegroups.com>
In reply to#105389
Just figured why:

If I type this on the kernel:

weirdList = [[0]*3]*5

weirdList
Out[257]: [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

weirdList[0][0] = 1

weirdList
Out[259]: [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]

All first elements of the sublists also changes. I dunno why...

[toc] | [prev] | [next] | [standalone]


#105396

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2016-03-21 19:24 +0000
Message-ID<mailman.459.1458588607.12893.python-list@python.org>
In reply to#105390
On 21/03/2016 18:30, Maurice wrote:
> Just figured why:
>
> If I type this on the kernel:
>
> weirdList = [[0]*3]*5
>
> weirdList
> Out[257]: [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>
> weirdList[0][0] = 1
>
> weirdList
> Out[259]: [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
>
> All first elements of the sublists also changes. I dunno why...
>

https://docs.python.org/3/faq/programming.html#why-did-changing-list-y-also-change-list-x

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#105491

Fromanantguptadbl@gmail.com
Date2016-03-22 07:23 -0700
Message-ID<1ec91e1c-9d0e-448b-a7b6-194ac105f8e2@googlegroups.com>
In reply to#105390
On Tuesday, March 22, 2016 at 12:01:10 AM UTC+5:30, Maurice wrote:
> Just figured why:
> 
> If I type this on the kernel:
> 
> weirdList = [[0]*3]*5
> 
> weirdList
> Out[257]: [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
> 
> weirdList[0][0] = 1
> 
> weirdList
> Out[259]: [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
> 
> All first elements of the sublists also changes. I dunno why...

When we write [[0] * 3] * 5, the [0] * 3 list is repeated 5 times
its something like
list,list,list,list,list

if we change the 1st element of list, it gets reflected on all the 5 copies

[toc] | [prev] | [next] | [standalone]


#105394

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2016-03-21 19:21 +0000
Message-ID<mailman.457.1458588135.12893.python-list@python.org>
In reply to#105389
On 21/03/2016 18:26, Maurice wrote:
> Hello, hope everything is okay. I think someone might have dealt with a similar issue I'm having.
>
> Basically I wanna do the following:
>
> I have a list such [6,19,19,21,21,21] (FYI this is the item of a certain key in the dictionary)
>
> And I need to convert it to a list of 32 elements (meaning days of the month however first element ie index 0 or day zero has no meaning - keeping like that for simplicity's sake).
> Therefore the resulting list should be:
> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
>
> So the list index should tell how many occurrences of a certain day in the original list.
>
> My attempt:
>
> weirdList = [[0]*32]*len(dict_days) #list's length should be how many keys in the dict.
>
> counter = 0
> k = 0
> for key in dict_days.keys():
>      for i in range(1,32):
>          if i in dict_days[key]:
>              counter = dict_days[key].count(i)
>              weirdList[k][i] = counter
>      dict_days[key] = weirdList[k]
>      k+=1
>
> However it does not work. weirdList seems to be always the same?
>
> Thanks in advance.
>

 >>> from collections import Counter
 >>> counts = Counter([6,19,19,21,21,21])
 >>> counts
Counter({21: 3, 19: 2, 6: 1})
 >>> weird_list = [0]*32
 >>> weird_list
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0]
 >>> for index, count in counts.items():
...     weird_list[index] = count
...
 >>> weird_list
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0]

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#105395

FromPeter Otten <__peter__@web.de>
Date2016-03-21 20:22 +0100
Message-ID<mailman.458.1458588144.12893.python-list@python.org>
In reply to#105389
Maurice wrote:

> Hello, hope everything is okay. I think someone might have dealt with a
> similar issue I'm having.
> 
> Basically I wanna do the following:
> 
> I have a list such [6,19,19,21,21,21] (FYI this is the item of a certain
> key in the dictionary)
> 
> And I need to convert it to a list of 32 elements (meaning days of the
> month however first element ie index 0 or day zero has no meaning -
> keeping like that for simplicity's sake). Therefore the resulting list
> should be:
> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
> 
> So the list index should tell how many occurrences of a certain day in the
> original list.
> 
> My attempt:
> 
> weirdList = [[0]*32]*len(dict_days) #list's length should be how many keys
> in the dict.

Rewrite the above as

inner = [0] * 32
weirdList = [inner] * len(dict_days)

Now it should be clearer that weirdList is

[inner, inner, inner, ...]

i. e. len(dict_days) times the same list of 32 zeros. When you modify 
weirdList[0] you also modify weirdList[1] etc. because these are the 
actually the same list.

For the inner list this is not a problem because 0 is immutable, so you can 
only replace it. If the inner list contained a mutable object you'd see the 
same "weird" behaviour you see for the outer list.

The fix is to use multiple inner lists:

not_so_weirdList = [[0]*32 for _ in range(len(dict_days))]

> counter = 0
> k = 0
> for key in dict_days.keys():
>     for i in range(1,32):
>         if i in dict_days[key]:
>             counter = dict_days[key].count(i)
>             weirdList[k][i] = counter
>     dict_days[key] = weirdList[k]
>     k+=1
> 
> However it does not work. weirdList seems to be always the same?

Instead of the list you could use a counter and get basically the same 
interface as long as you ensure that the second index satisfies 0<=index<32:

import collections

for key, values in dict_days.items():
    dict_days[key] = collections.Counter(values)

[toc] | [prev] | [next] | [standalone]


#105401

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-03-21 20:03 +0000
Message-ID<87bn67oayt.fsf@bsb.me.uk>
In reply to#105389
Maurice <mauricioliveiraguarda@gmail.com> writes:

> Hello, hope everything is okay. I think someone might have dealt with
> a similar issue I'm having.
>
> Basically I wanna do the following:
>
> I have a list such [6,19,19,21,21,21] (FYI this is the item of a
>certain key in the dictionary)
>
> And I need to convert it to a list of 32 elements (meaning days of the
> month however first element ie index 0 or day zero has no meaning -
> keeping like that for simplicity's sake).

> Therefore the resulting list should be:
> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]

How about

  reduce(lambda counts, day: counts[:day] + [counts[day]+1] + counts[day+1:],
         days, [0]*32)

?  (reduce is in functools).

Not efficient, but sometimes you just want to the job done.

More efficient would be:

  def inc_day(counts, day): counts[day] += 1; return counts
  reduce(inc_day, days, [0]*32)

For experts here: why can't I write a lambda that has a statement in it
(actually I wanted two: lambda l, i: l[i] += 1; return l)?

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#105402

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-21 14:12 -0600
Message-ID<mailman.461.1458591209.12893.python-list@python.org>
In reply to#105401
On Mon, Mar 21, 2016 at 2:03 PM, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> For experts here: why can't I write a lambda that has a statement in it
> (actually I wanted two: lambda l, i: l[i] += 1; return l)?

https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-contain-statements

[toc] | [prev] | [next] | [standalone]


#105423

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-03-22 00:31 +0000
Message-ID<87oaa7mjyh.fsf@bsb.me.uk>
In reply to#105402
Ian Kelly <ian.g.kelly@gmail.com> writes:

> On Mon, Mar 21, 2016 at 2:03 PM, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> For experts here: why can't I write a lambda that has a statement in it
>> (actually I wanted two: lambda l, i: l[i] += 1; return l)?
>
> https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-contain-statements

Thanks.  That makes it clear that it's just for syntactic and not
semantic reasons.

However, the explanation ("because Python’s syntactic framework can't
handle statements nested inside expressions") seemed, at first, to be
saying you can't because you can't!  But the term "syntactic framework"
hints that it's not really just an arbitrary choice -- that this is
something about the way Python is parsed that make this choice
inevitable.  Is it to do with the way that indentation has a syntactic
role?

To phrase my question in terms of syntax, why is the : in lambda
followed by a test (the top-level production for an expression in the
grammar) but the : in a function definition is followed by a suite?  I
expected them to be both a suite, but presumably something goes horribly
wrong if that were done.  Now I'm wondering what.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#105428

FromChris Angelico <rosuav@gmail.com>
Date2016-03-22 11:58 +1100
Message-ID<mailman.477.1458608322.12893.python-list@python.org>
In reply to#105423
On Tue, Mar 22, 2016 at 11:31 AM, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> However, the explanation ("because Python’s syntactic framework can't
> handle statements nested inside expressions") seemed, at first, to be
> saying you can't because you can't!  But the term "syntactic framework"
> hints that it's not really just an arbitrary choice -- that this is
> something about the way Python is parsed that make this choice
> inevitable.  Is it to do with the way that indentation has a syntactic
> role?
>
> To phrase my question in terms of syntax, why is the : in lambda
> followed by a test (the top-level production for an expression in the
> grammar) but the : in a function definition is followed by a suite?  I
> expected them to be both a suite, but presumably something goes horribly
> wrong if that were done.  Now I'm wondering what.

A "suite" is a series of statements - in common parlance, a block of
code. A "test" is a type of expression (there are a variety of these
kind of things, and they define operator precedence).

Part of the trickiness of permitting statements inside expressions is
that it would get confusing - not that it'd be truly ambiguous and
impossible to parse, but that small errors could result in peculiar
misinterpretations of subsequent code, which means the error messages
would be harder to understand. There are already a few places like
that:

functioncall( # ) # oops, forgot the close parenthesis
name = value
othername = othervalue

You'll get a SyntaxError on the last line, despite it being
functionally identical to the second. And it's just "invalid syntax",
the most completely unhelpful message. (This situation is considered
worthwhile, though. Named arguments and assignment both make way too
much sense to break one of them.) Now imagine if every "lambda" in the
code could result in the same kind of thing; currently, the keyword
"lambda" must be followed by a (possibly empty) argument list and then
an expression, which must either be entirely within one line, or have
parentheses around it. If, instead, "lambda x:" introduced a suite,
you'd have errors coming up much further down.

Having full statement syntax inside an expression isn't always even a
benefit. It's often a major cost to readability - just have a look at
a big pile of JavaScript callback code some time. (Although, to be
fair, function() {...} isn't the only readability problem there.) And
it has a debugging cost that gets significantly higher when you don't
have braces to delimit blocks.

ChrisA

[toc] | [prev] | [next] | [standalone]


#105443

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2016-03-22 15:34 +1100
Message-ID<56f0cb6d$0$1607$c3e8da3$5496439d@news.astraweb.com>
In reply to#105423
On Tuesday 22 March 2016 11:31, Ben Bacarisse wrote:

> Ian Kelly <ian.g.kelly@gmail.com> writes:
> 
>> On Mon, Mar 21, 2016 at 2:03 PM, Ben Bacarisse <ben.usenet@bsb.me.uk>
>> wrote:
>>> For experts here: why can't I write a lambda that has a statement in it
>>> (actually I wanted two: lambda l, i: l[i] += 1; return l)?
>>
>> https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-
contain-statements
> 
> Thanks.  That makes it clear that it's just for syntactic and not
> semantic reasons.
> 
> However, the explanation ("because Python’s syntactic framework can't
> handle statements nested inside expressions") seemed, at first, to be
> saying you can't because you can't!  But the term "syntactic framework"
> hints that it's not really just an arbitrary choice -- that this is
> something about the way Python is parsed that make this choice
> inevitable.  Is it to do with the way that indentation has a syntactic
> role?

Don't ask me for a link, because I'm lazy, but this has been discussed like 
a bazillion times in the past, here, and on the Python-Ideas and Python-Dev 
mailing lists. No offense intended, but if you want definitive statements 
from the core developers, you can google for them :-)

But in a nutshell, there are four reasons for the limitation on Python's 
lambda statement:

- The use of indentation makes it hard to insert arbitrary statements into 
an expression without confusing the parser.

- Guido has a strict rule that Python's syntax must be parsable using a 
relatively simply parser. A LL(1) parser, if I remember correctly. So none 
of the fancy tricks and hard-to-understand syntax rules that (say) C++ uses.

- Given those limitations, nobody has been able to come up with syntax that 
has broad support.

- And besides, quite a large number of people believe that limiting lambda 
to simple, single-expression cases is a feature, not a bug.


Nobody has quite ruled out multi-statement lambda, or code blocks, but after 
20+ years of people trying to find syntax which works but isn't hated, and 
failing, I think it's probably safe to say it isn't going to happen.



-- 
Steve

[toc] | [prev] | [next] | [standalone]


#105403

FromIan Kelly <ian.g.kelly@gmail.com>
Date2016-03-21 14:14 -0600
Message-ID<mailman.462.1458591310.12893.python-list@python.org>
In reply to#105401
On Mon, Mar 21, 2016 at 2:12 PM, Ian Kelly <ian.g.kelly@gmail.com> wrote:
> On Mon, Mar 21, 2016 at 2:03 PM, Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> For experts here: why can't I write a lambda that has a statement in it
>> (actually I wanted two: lambda l, i: l[i] += 1; return l)?
>
> https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-contain-statements

tl;dr: If you want a function with a statement in it, use def, not lambda.

[toc] | [prev] | [next] | [standalone]


#105418

FromSteven D'Aprano <steve@pearwood.info>
Date2016-03-22 11:13 +1100
Message-ID<56f08e3f$0$1619$c3e8da3$5496439d@news.astraweb.com>
In reply to#105389
On Tue, 22 Mar 2016 05:26 am, Maurice wrote:

> I have a list such [6,19,19,21,21,21] (FYI this is the item of a certain
> key in the dictionary)
> 
> And I need to convert it to a list of 32 elements (meaning days of the
> month however first element ie index 0 or day zero has no meaning -
> keeping like that for simplicity's sake). Therefore the resulting list
> should be:
> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
> 
> So the list index should tell how many occurrences of a certain day in the
> original list.

the_list = [6,19,19,21,21,21]
days = [0]*32
for item in the_list:
    days[item] += 1



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#105432

FromPaul Rubin <no.email@nospam.invalid>
Date2016-03-21 18:35 -0700
Message-ID<87twjzz44v.fsf@jester.gateway.pace.com>
In reply to#105389
Maurice <mauricioliveiraguarda@gmail.com> writes:
> I have a list such [6,19,19,21,21,21]
> Therefore the resulting list should be:
> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]

Rather than a sparse list you'd typically want a dictionary (untested):

  from collections import defaultdict
  the_list = [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
  ...
  days = defaultdict(int)
  for t in the_list:
     days[t] += 1

this results in days being the defaultdict { 6:1, 19:2, 21:3 }.

defaultdict is a special type of dictionary where if you try to access a
non-existent element, it gets created and initialized with the data
constructor you made it with.  In this case the data constructor is int,
and int() makes the number 0, so the defaultdict elements are
initialized to 0.

[toc] | [prev] | [next] | [standalone]


#105458

FromSteven D'Aprano <steve@pearwood.info>
Date2016-03-22 21:49 +1100
Message-ID<56f12322$0$1607$c3e8da3$5496439d@news.astraweb.com>
In reply to#105432
On Tue, 22 Mar 2016 12:35 pm, Paul Rubin wrote:

> Maurice <mauricioliveiraguarda@gmail.com> writes:
>> I have a list such [6,19,19,21,21,21]
>> Therefore the resulting list should be:
>> [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
> 
> Rather than a sparse list you'd typically want a dictionary (untested):
> 
>   from collections import defaultdict
>   the_list = [0,0,0,0,0,0,1,0,0,0...,2,0,3,0...0]
>   ...
>   days = defaultdict(int)
>   for t in the_list:
>      days[t] += 1
> 
> this results in days being the defaultdict { 6:1, 19:2, 21:3 }.

For just 3 items out of 32, doing this as an optimisation is barely worth
it. Using Python 3.4, I get 168 bytes for the list solution and 152 bytes
for a default dict solution:

py> print(days)
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0]
py> sys.getsizeof(days)
168

py> from collections import defaultdict
py> d = defaultdict(int)
py> d.update({ 6:1, 19:2, 21:3 })
py> sys.getsizeof(d)
152

By all means use whichever solution suits you best, but don't expect to save
much memory in a "spare array" of only 32 items :-)



-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web