3

I am learning RxPY , so I need to write some code which can split each word by its first character. The results must look something like this:

{'a': ['a'], 't': ['the','the'], 'l': ['low','lazy']}

What I've tried.

from rx import Observable , Observer

list =['A', 'The', 'the', 'LAZY', 'Low']

o = Observable . from_ ( list )\
. filter (lambda i: i[0] == 'A' or 'Z' )\

words = o.map(lambda s: s.lower().split())

word_each = words.flat_map(lambda s: s)

ss = word_each.to_dict(lambda x: x[:1], lambda x : x)\
    .subscribe(lambda val: print(val))

So, how can I solve this problem? I am thinking about grouping each word by it's first character but I dont know how.

[CLOSED]
Alesha
  • 31
  • 2

4 Answers4

1

I know nothing about RxPy, but you can do it in one line with vanilla python using dict and list comps

  d = {el[0].lower(): [e.lower() for e in lst if e[0].lower() == el[0].lower()] for el in lst}
0TTT0
  • 1,288
  • 1
  • 13
  • 23
1

Using rx, if you really want to do it in a difficult way.

>>> from rx import Observable
>>> from collections import defaultdict
>>> source = Observable.from_(['A', 'The', 'the', 'LAZY', 'Low'])
>>> result = defaultdict(list)
>>> def add(value):
...     value_content = '{0}'.format(value)
...     result[value_content[0].lower()].append(value_content)
... 
>>> s = source.subscribe(on_next=lambda value: add(value), on_completed=lambda: print('Finished'))
Finished
>>> result
defaultdict(<class 'list'>, {'a': ['A'], 't': ['The', 'the'], 'l': ['LAZY', 'Low']})

Use dict(result) as shown in Chiheb Nexus' answer if you need this in the form of a dictionary.

I changed the name of your list to my_list.

>>> my_list =['A', 'The', 'the', 'LAZY', 'Low']
>>> from itertools import groupby
>>> {key: list(val) for (key, val) in  groupby(sorted(my_list), key=lambda x: x[0].lower())}
{'a': ['A'], 't': ['The', 'the'], 'l': ['LAZY', 'Low']}
Bill Bell
  • 21,021
  • 5
  • 43
  • 58
  • doesn't match her output `{'a': ['a'], 't': ['the','the'], 'l': ['low','lazy']}`, just lower your strings – 0TTT0 Nov 05 '17 at 18:31
0

You can use defaultdict module to accomplish the task. Here is an example:

from collections import defaultdict
my_list = ['A', 'The', 'the', 'LAZY', 'Low']

def split_words(a):
    b = defaultdict(list)
    for k in a:
        b[k[0].lower()].append(k.lower())
    return b

>>> split_words(my_list)
    defaultdict(list, {'a': ['a'], 'l': ['lazy', 'low'], 't': ['the', 'the']})
>>> dict(split_words(my_list))
    {'a': ['a'], 'l': ['lazy', 'low'], 't': ['the', 'the']}
Chiheb Nexus
  • 9,104
  • 4
  • 30
  • 43
  • 1
    I thought you had scooped me but I don't think this is what she's asking for. – Bill Bell Nov 05 '17 at 18:55
  • @BillBell Yes indeed. But no one is answering to this question using RxPy, so i thought that she can use another work around if she is in really need. – Chiheb Nexus Nov 05 '17 at 18:57
  • I'd never heard of rx, I read through the intro and wrote an answer. – Bill Bell Nov 05 '17 at 18:59
  • @BillBell Well, you've answered using the right tool and your answer should be validated ... Otherwise, if it's a homework, it doesn't matter a lot, at least for me, because i never heard of RxPy too. I'm learning from your answer. – Chiheb Nexus Nov 05 '17 at 19:01
  • 1
    Read the intro, it's probably better! – Bill Bell Nov 05 '17 at 19:02
0

Update May 2019 using RxPy v6

RxPy really shines when performing these types of transformations (although acknowledged you could equally apply a pragmatic solution in plain python).

Here is a straightforward solution:

from rx import Observable

list = ['A', 'The', 'the', 'LAZY', 'Low']

Observable.from_(list) \
    .map(lambda s: s.lower()) \
    .group_by(lambda s: s[0]) \
    .flat_map(lambda grp: grp.to_list()) \
    .to_dict(lambda grp: grp[0][0], lambda grp: grp) \
    .subscribe(print)

Output as requested:

# {'a': ['a'], 't': ['the', 'the'], 'l': ['lazy', 'low']}

The "algorithm" is:

  • Make the list of words an Observable.
  • Map over each word and convert to lowercase.
  • Group each word by its first letter.
  • Use flatmap to unnest as we convert each grouping to a list. At this point, the interim result looks as follows:

    ['a']
    ['the', 'the']
    ['lazy', 'low']
    
  • Now, use the to_dict operator to convert to a single dictionary, whose keys are the first letter of the first item in each grouping (list).

  • Subscribe to the Observable to execute the pipeline.
arcseldon
  • 35,523
  • 17
  • 121
  • 125