Python Forum
Slicing Python list of strings into individual characters
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Slicing Python list of strings into individual characters
#1
I’m trying to get slice a list of strings into individual characters ...but using slicing.

Here is my list:

first_list = ["apples", "bananas", "oranges",]
Here is the end result and what I am trying to achieve:

['a', 'p', 'p', 'l', 'e', 's', 'b', 'a', 'n', 'a', 'n', 'a', 's', 'o', 'r', 'a', 'n', 'g', 'e', 's']
I succeeded using a for loop:

for item in first_list:
   for character in item:
       second_list.append(character)
print(second_list)
That’s a basic for loop which I completely understand the syntax and logic.

But I am now trying to come up with an alternate solution this time using slicing. Here is my valiant attempt:

print(third_list.append(first_list[:][:]))
My interpreter prints ‘None’ with that code. I am not sure why. Could someone explain?

My humble lucid, cerebral explanation for that one-liner is: Python is printing the third_list variable which is a composition of each letter (appended together) contained in first_list. I’m obviously mistaken because the result is just None. Could someone please correct my explanation here?

I suppose a further and more important question that I have is this: Who among you could perform the same for loop operation that worked the first time but instead using two slices (as I have awkwardly attempted but failed to do)?
Reply
#2
?
sum(map(list, first_list), [])
Reply
#3
(Apr-15-2019, 02:35 AM)Drone4four Wrote:
for item in first_list:
   for character in item:
       second_list.append(character)
print(second_list)
That’s a basic for loop which I completely understand the syntax and logic.

If you completely understand syntax and logic of this you should move to next level - list comprehension. Same result with less code:

>>> [character for item in first_list for character in item]
Is there any particular reason you want to use slicing?

(Apr-15-2019, 02:35 AM)Drone4four Wrote:
print(third_list.append(first_list[:][:]))
My interpreter prints ‘None’ with that code. I am not sure why. Could someone explain?

List method .append changed third_list in-place and returned None (all Python function/methods return/yield value or None). If you want to see what happened you should print out third_list not the result of the method.

Some exaples:

>>> def do_nothing():
...     pass
...
>>> do_nothing()         # nothing happens
>>> print(do_nothing())
None                     # function returns None
>>> def say_hello():
...     print('Hello')
...
>>> say_hello()
Hello
>>> print(say_hello())
Hello                    # functions prints
None                     # function returns None as there is no return (or yield)
>>> def return_five():
...     return 5
...
>>> return_five():
5
>>> print(return_five())
5                        
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply
#4
To understand scidam's solution, you need knowledge about the sum function and __add__ operation of lists.
In addition the sum function is supplied with an initial value.
The map function takes the first element, which is a string.
The map function calls list with the string-element.
The sum function takes this element and adds it to the initial value, which is a list.


first_list = ["apples", "bananas", "oranges",]
sum(map(list, first_list), [])
A more naive solution is this:
first_list = ["apples", "bananas", "oranges",]
concatenated_str = first_list[0] + first_list[1] + first_list[2]
flat_list = list(concatenated_str) # turns the string into a list
Another solution can be found in the module itertools.

from itertools import chain


first_list = ["apples", "bananas", "oranges",]
flat_list = chain.from_iterable(first_list)
print(flat_list)
Output:
<itertools.chain at 0x7f0857c921d0>
Until now this piece of code has not done much. You need to iterate over the object, to get all elements out.
The benefit is, that you can decide if you want to have a tuple, list, set or something else.

Consume the iterator:
solution = list(flat_list)
print(solution)
# this does not work!
# print(list(flat_list))
# flat_list is already exhausted and does not start from the beginning
# this is why i assigned the result to solution
Another solution can be yield from.

def flatten(iterable):
    for element in iterable:
        yield from element
This generator goes 2 levels deep. First it iterates over iterable, then the element you got is the string.
This string is iterated by yield from. If you write this less dense, it looks like this:


def flatten(iterable):
    for element in iterable:
        for char in element:
            yield char
This function is used, like the other generators. (Generators are lazy evaluated).

print(list(flatten(first_list)))
Output:
['a', 'p', 'p', 'l', 'e', 's', 'b', 'a', 'n', 'a', 'n', 'a', 's', 'o', 'r', 'a', 'n', 'g', 'e', 's']
My code examples are always for Python >=3.6.0
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
Thank you @scidam, @perfringo, @DeaD_EyE for your helpful replies.

There is a lot here. I’ve reviewed all of your posts a few times and have played around with different combinations with all of your code samples in my Python interpreter.

For now I am going share some things I learned from exploring @DeaD_EyE’s use of the chain function from the itertools library. When you first shared the chain function, you used this:

from itertools import chain

first_list = ["apples", "bananas", "oranges",]
flat_list = chain.from_iterable(first_list)
print(flat_list)
I didn’t really understand how or why that code worked. So I found the official Python doc for the function. From this doc:

Quote:Alternate constructor for chain(). Gets chained inputs from a single iterable argument that is evaluated lazily. Roughly equivalent to:
def from_iterable(iterables):
    # chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
    for it in iterables:
        for element in it:
            yield element

This sparse explanation went over my head, in part because the Python docs are written by programmers for programmers. So I continued reading your post, @DeaD_EyE and you basically re-phrased the method using your own language:

Quote:This generator goes 2 levels deep. First it iterates over iterable, then the element you got is the string.
This string is iterated by yield from.

I find this to be a clearer explanation of the process. Thank you.

I still had to look up the yield keyword for functions. Check out this SO post titled, “What does the “yield” keyword do?”. From there I learned that yield is similar to return but for generators where an iterable is only iterated over once.

I’m not sure I understand what you mean when you say “consume the iterator”. You explained that print(list(flat_list)) wouldn’t work because the last was supposed to be already exhausted. But I entered each line into my Python interpreter and there was no traceback or issue presented. It turns out there was no need to assign the result to the solution after all. See attached for an image of my interpreter. @DeaD_EyE: What could you (or anyone else reading this) make of this?

Attached Files

Thumbnail(s)
   
Reply
#6
(Apr-17-2019, 12:35 AM)Drone4four Wrote: I’m not sure I understand what you mean when you say “consume the iterator”. You explained that print(list(flat_list)) wouldn’t work because the last was supposed to be already exhausted. But I entered each line into my Python interpreter and there was no traceback or issue presented.

There is subtle difference in here:

In [8]: from itertools import chain                                                                                             

In [9]: flat_list = chain.from_iterable(['apples', 'bananas', 'oranges'])                                                       

In [10]: print(flat_list)                    # printing out object, not consuming iterator                                                                                
<itertools.chain object at 0x10cd56048>       

In [11]: list(flat_list)                     # consuming iterator i.e. iterating over and creating list                                                                                  
Out[11]: 
['a', /../  's']

In [12]: list(flat_list)                     # consuming exhausted iterator                                                                                                                 
Out[12]: []

(Apr-15-2019, 02:35 AM)Drone4four Wrote: I’m trying to get slice a list of strings into individual characters ...but using slicing.

I observed that there is no answer to original question. I have no idea why would anyone want to do it as there are built-in tools for that. However, following silly code uses slicing as aftertought to get list of individual characters:

 
>>> lst = ['apples', 'bananas', 'oranges']
>>> [fruit[i:i+1] for fruit in lst for i in range(len(fruit))]
I'm not 'in'-sane. Indeed, I am so far 'out' of sane that you appear a tiny blip on the distant coast of sanity. Bucky Katt, Get Fuzzy

Da Bishop: There's a dead bishop on the landing. I don't know who keeps bringing them in here. ....but society is to blame.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Extract continuous numeric characters from a string in Python Robotguy 2 653 Jan-16-2021, 12:44 AM
Last Post: snippsat
  Python win32api keybd_event: How do I input a string of characters? JaneTan 3 867 Oct-19-2020, 04:16 AM
Last Post: deanhystad
  slicing and indexing a list example leodavinci1990 4 690 Oct-12-2020, 06:39 AM
Last Post: bowlofred
  Introduction to escaping characters in strings Geelong_crazy 1 1,037 Jul-18-2020, 06:58 PM
Last Post: DT2000
  read individual nodes from an xml url using pandas mattkaplan27 5 926 Jul-05-2020, 10:06 PM
Last Post: snippsat
  How to find the first and last of one of several characters in a list of strings? tadsss 2 844 Jun-02-2020, 05:23 PM
Last Post: bowlofred
  Remove escape characters / Unicode characters from string DreamingInsanity 5 3,857 May-15-2020, 01:37 PM
Last Post: snippsat
  Python Consecutive characters vijju56 4 1,787 Apr-22-2020, 11:03 AM
Last Post: TomToad
  Replacing characters in a string with a list cjms981 1 844 Dec-30-2019, 10:50 PM
Last Post: micseydel
  Help with slicing a list FWendeburg 3 1,132 Dec-02-2019, 04:57 PM
Last Post: michael1789

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020