Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I actually had a great use case for this last week. Needed to flatten a list of nested dicts, e.g.:

  [
    {"name": "/dev/loop0"},
    {"name": "/dev/loop1"},
    {"name": "/dev/loop2"},
    {
      "name": "/dev/sda",
      "children":
        [
          {
            "name": "/dev/sda1",
            "children":
              [{"name": "/dev/mapper/lubuntu--vg-root"}, {"name": "/dev/mapper/lubuntu--vg-swap_1"}],
          },
        ],
    },
    {"name": "/dev/sdb", "children": [{"name": "/dev/sdb1"}, {"name": "/dev/sdb2"}]},
    {"name": "/dev/sdc", "children": [{"name": "/dev/sdc1"}, {"name": "/dev/sdc9"}]},
  ]
Wound up writing a recursive generator (with some help from #python on IRC):

  def flatten(items):
      for item in items:
          yield {k:v for k,v in item.items() if k != 'children'}
          if 'children' in item:
              yield from flatten(item['children'])
which results in:

  [{'name': '/dev/loop0'},
   {'name': '/dev/loop1'},
   {'name': '/dev/loop2'},
   {'name': '/dev/sda'},
   {'name': '/dev/sda1'},
   {'name': '/dev/mapper/lubuntu--vg-root'},
   {'name': '/dev/mapper/lubuntu--vg-swap_1'},
   {'name': '/dev/sdb'},
   {'name': '/dev/sdb1'},
   {'name': '/dev/sdb2'},
   {'name': '/dev/sdc'},
   {'name': '/dev/sdc1'},
   {'name': '/dev/sdc9'}]


I see your function and "yield" (pun definitely intended) the following:

    def flatten(children=[], **other):
        if other: yield other
        for child in children: yield from flatten(**child)


That's pretty brilliant to use `children` as the keyword name, thanks!


Thanks for the example, but I was more looking for something that uses "generator.send(...)". I definitely agree that yielding items out of generators is extremely useful, but not so sure on examples of generators that are sent values.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: