Removing a string from a list - python

I create a list, and I want to remove a string from it.
Ex:
>>> myList = ['a', 'b', 'c', 'd']
>>> myList = myList.remove('c')
>>> print(myList)
None
What am I doing wrong here? All I want is 'c' to be removed from myList!

I am not sure what a is (I am guessing another list), you should do myList.remove() alone, without assignment.
Example -
>>> myList = ['a', 'b', 'c', 'd']
>>> myList.remove('c')
>>> myList
['a', 'b', 'd']
myList.remove() does not return anything, hence when you do myList = <anotherList>.remove(<something>) it sets myList to None

Remember that lists are mutable, so you can simply call remove on the list itself:
>>> myList = ['a', 'b', 'c', 'd']
>>> myList.remove('c')
>>> myList
['a', 'b', 'd']
The reason you were getting None before is because remove() always returns None

Just an addition to Anand's Answer,
mylist = mylist.remove('c')
The above code will return 'none' as the return type for my list. So you want to keep it as
mylist.remove('c')

The remove() function doesn't return anything, it modifies the list in place. If you don't assign it to a variable you will see that myList doesn't contain c anymore.

Related

Splitting string values in list into individual values, Python

I have a list of values in which some values are words separated by commas, but are considered single strings as shown:
l = ["a",
"b,c",
"d,e,f"]
#end result should be
#new_list = ['a','b','c','d','e','f']
I want to split those strings and was wondering if there's a one liner or something short to do such a mutation. So far what, I was thinking of just iterating through l and .split(',')-ing all the elements then merging, but that seems like it would take a while to run.
import itertools
new_list = list(itertools.chain(*[x.split(',') for x in l]))
print(new_list)
>>> ['a', 'b', 'c', 'd', 'e', 'f']
Kind of unusual but you could join all your elements with , and then split them:
l = ["a",
"b,c",
"d,e,f"]
newList = ','.join(l).split(',')
print(newList)
Output:
['a', 'b', 'c', 'd', 'e', 'f']
Here's a one-liner using a (nested) list comprehension:
new_list = [item for csv in l for item in csv.split(',')]
See it run here.
Not exactly a one-liner, but 2 lines:
>>> l = ["a",
"b,c",
"d,e,f"]
>>> ll =[]
>>> [ll.extend(x.split(',')) for x in l]
[None, None, None]
>>> ll
['a', 'b', 'c', 'd', 'e', 'f']
The accumulator needs to be created separately since x.split(',') can not be unpacked inside a comprehension.

List of lists: Changing all references with one assignment?

Rationale: I start a script with a list that contains multiple heaps. At every step, I want to "join" heaps, but keep both joined indexes pointing to the same element.
In short, given a list of mutable elements, such that list[a] is list[b] returns True, how can I assign (list[a] = [new]) while keeping list[a] and list[b] references to the same mutable container?
So for example, if each heap was represented by a letter, we would have
t is ['a', 'b', 'c', 'd']
t is ['ac', 'b', 'ac', 'd'] (0 and 2 merge)
t is ['abc', 'abc', 'abc', 'd'] (0 and 1 merge, but since 0 also refers to 2, it is as if 0/2 and 1 merged... into 0/1/2)
at this stage, if I did a set(map(id, t)), I would expect it to only have TWO elements.
my problem is that I cannot seem to affect the object being pointed to directly, so I have to iterate over the entire list, picking out any ids that match either merge index, and assign directly.
is there any way to change the underlying object rather than all pointers to it?
Full Example of desired behavior:
>>> my_list = [['a'], ['b'], ['c']]
>>> merge(my_list, 0, 2) # mutates, returns None
>>> my_list
[['a', 'c'], ['b'], ['a', 'c']]
>>> my_list[0] is my_list[2]
True
>>> merge(my_list, 0, 1)
>>> my_list
[['a', 'c', 'b'], ['a', 'c', 'b'], ['a', 'c', 'b']]
>>> my_list[0] is my_list[1]
True
>>> my_list[1] is my_list[2]
True
The problem is that, if within merge I simply call
my_list[arg1] = my_list[arg2] = my_list[arg1]+my_list[arg2]
it ONLY affects the entries at arg1 and arg2. I want it to affect any other entries that may point to the elements at either my_list[arg1] or my_list[arg2], so that eventually my_list is just a collection of pointers to the same big heap, that has absorbed all the little ones.
This is as close as you are going to get:
def merge(primary, first, second):
primary[first] += primary[second]
primary[second] = primary[first]
first = ['a']
second = ['b']
third = ['c']
main = [first, second, third]
print(main)
merge(main, 0, 2)
print(main)
assert main[0] is main[2]
merge(main, 0, 1)
print(main)
assert main[1] is main[2]
print(first, second, third)
and the printout:
[['a'], ['b'], ['c']]
[['a', 'c'], ['b'], ['a', 'c']]
[['a', 'c', 'b'], ['a', 'c', 'b'], ['a', 'c', 'b']]
(['a', 'c', 'b'], ['b'], ['c'])
As you can see, the list elements all end up being the same object, but the lists that went into the main list are not.
edit
Unfortunately, this also fails if you don't include the first list element in every merge.
So there are no short-cuts here. If you want every element to either be the same element, or just be equal, you are going to have to traverse the list to get it done:
def merge(primary, first, second):
targets = primary[first], primary[second]
result = primary[first] + primary[second]
for index, item in enumerate(primary):
if item in targets:
primary[index] = result
Chain assignment:
>>> my_list = [['a'], ['b'], ['c']]
>>> my_list[0] = my_list[2] = my_list[0]+my_list[2]
>>> my_list
[['a', 'c'], ['b'], ['a', 'c']]
>>> my_list[0] += [1,2,3]
>>> my_list
[['a', 'c', 1, 2, 3], ['b'], ['a', 'c', 1, 2, 3]]
>>>
If you do a=c=a+c first, it produce a==c==_list_object_001; when you do a=b=a+b 2nd, it produce a==b==_list_object_002, so it went wrong.
You can't do this even with a pointer if you don't take care of the order of assignment. I think you should maintain a map to get things right.
As far as I can see, I don't think it's possible to do this using the mutability of python lists. If you have elements X and Y, both of which are already amalgamations of other elements, and you want to merge them, list mutability will not be able to telegraph the change to both sides. You can make X, Y and all the elements pointing at the same object as X be the same, or you can make X, Y and all the elements pointing at the same object as Y be the same, but not both.
I think the best bet is to define a custom object to represent the elements, which has a notion of parent nodes and ultimate parent nodes.
class Nodes(object):
def __init__(self, input1):
self.parent = None
self.val = [input1]
def ultimate_parent(self):
if self.parent:
return self.parent.ultimate_parent()
else:
return self
def merge(self, child):
self.ultimate_parent().val += child.ultimate_parent().val
child.ultimate_parent().parent = self.ultimate_parent()
def __repr__(self):
return str(self.ultimate_parent().val)
def merge(node_list, i, j):
node_list[i].merge(node_list[j])
list1 = [Nodes(x) for x in 'abcd']
print list1
merge(list1, 0, 2)
print list1
merge(list1, 1, 3)
print list1
merge(list1, 0, 1)
print list1
This will output:
[['a', 'c'],['b'],['a', 'c'],['d']]
[['a', 'c'],['b', 'd'],['a', 'c'],['b', 'd']]
[['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd'],['a', 'c', 'b', 'd']]

Python: Search list and give boolean

If I have a list like so:
List = ['a', 'b', 'c', 'd', 'e',]
what is the simplest way to get a Boolean answer if, I for instance asked it if 'g' was inside this list?
print 'g' in ['a', 'b', 'c', 'd']
l = ['a','b','c','d']
if 'g' in l:
print True
List = ['a', 'b', 'c', 'd', 'e']
def inlist (lst, character):
if character in lst and type(lst) is list:
return True
else:
return False
print inlist(List, 'g')
As you expect, this prints: False
NOTE: try to name your lists other than List, as that can cause some confusion when reading.

Python: filtering lists by indices

In Python I have a list of elements aList and a list of indices myIndices. Is there any way I can retrieve all at once those items in aList having as indices the values in myIndices?
Example:
>>> aList = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> myIndices = [0, 3, 4]
>>> aList.A_FUNCTION(myIndices)
['a', 'd', 'e']
I don't know any method to do it. But you could use a list comprehension:
>>> [aList[i] for i in myIndices]
Definitely use a list comprehension but here is a function that does it (there are no methods of list that do this). This is however bad use of itemgetter but just for the sake of knowledge I have posted this.
>>> from operator import itemgetter
>>> a_list = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> my_indices = [0, 3, 4]
>>> itemgetter(*my_indices)(a_list)
('a', 'd', 'e')
Indexing by lists can be done in numpy. Convert your base list to a numpy array and then apply another list as an index:
>>> from numpy import array
>>> array(aList)[myIndices]
array(['a', 'd', 'e'],
dtype='|S1')
If you need, convert back to a list at the end:
>>> from numpy import array
>>> a = array(aList)[myIndices]
>>> list(a)
['a', 'd', 'e']
In some cases this solution can be more convenient than list comprehension.
You could use map
map(aList.__getitem__, myIndices)
or operator.itemgetter
f = operator.itemgetter(*aList)
f(myIndices)
If you do not require a list with simultaneous access to all elements, but just wish to use all the items in the sub-list iteratively (or pass them to something that will), its more efficient to use a generator expression rather than list comprehension:
(aList[i] for i in myIndices)
Alternatively, you could go with functional approach using map and a lambda function.
>>> list(map(lambda i: aList[i], myIndices))
['a', 'd', 'e']
I wasn't happy with these solutions, so I created a Flexlist class that simply extends the list class, and allows for flexible indexing by integer, slice or index-list:
class Flexlist(list):
def __getitem__(self, keys):
if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
return [self[k] for k in keys]
Then, for your example, you could use it with:
aList = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
myIndices = [0, 3, 4]
vals = aList[myIndices]
print(vals) # ['a', 'd', 'e']

python items in list added to string

I am trying to concatenate items in a list onto a string.
list = ['a', 'b', 'c', 'd']
string = ''
for i in list:
string.join(str(i))
You don't need a loop:
items = ['a', 'b', 'c', 'd']
result = "".join(items)
Note that it's a bad idea to use list as the name of a variable, because that prevents you from using list to mean the built-in type.
Is this what you are looking for?
>>> my_list = ['a', 'b', 'c', 'd']
>>> "".join(my_list)
'abcd'
You shouldn't use list as a variable name, since this will shadow the built-in class list.

Categories