Add to integers in a list - python

I have a list of integers and I was wondering if it would be possible to add to individual integers in this list.

You can append to the end of a list:
foo = [1, 2, 3, 4, 5]
foo.append(4)
foo.append([8,7])
print(foo) # [1, 2, 3, 4, 5, 4, [8, 7]]
You can edit items in the list like this:
foo = [1, 2, 3, 4, 5]
foo[3] = foo[3] + 4
print(foo) # [1, 2, 3, 8, 5]
Insert integers into the middle of a list:
x = [2, 5, 10]
x.insert(2, 77)
print(x) # [2, 5, 77, 10]

Here is an example where the things to add come from a dictionary
>>> L = [0, 0, 0, 0]
>>> things_to_add = ({'idx':1, 'amount': 1}, {'idx': 2, 'amount': 1})
>>> for item in things_to_add:
... L[item['idx']] += item['amount']
...
>>> L
[0, 1, 1, 0]
Here is an example adding elements from another list
>>> L = [0, 0, 0, 0]
>>> things_to_add = [0, 1, 1, 0]
>>> for idx, amount in enumerate(things_to_add):
... L[idx] += amount
...
>>> L
[0, 1, 1, 0]
You could also achieve the above with a list comprehension and zip
L[:] = [sum(i) for i in zip(L, things_to_add)]
Here is an example adding from a list of tuples
>>> things_to_add = [(1, 1), (2, 1)]
>>> for idx, amount in things_to_add:
... L[idx] += amount
...
>>> L
[0, 1, 1, 0]

fooList = [1,3,348,2]
fooList.append(3)
fooList.append(2734)
print(fooList) # [1,3,348,2,3,2734]

If you try appending the number like, say
listName.append(4) , this will append 4 at last.
But if you are trying to take <int> and then append it as, num = 4 followed by listName.append(num), this will give you an error as 'num' is of <int> type and listName is of type <list>. So do type cast int(num) before appending it.

Yes, it is possible since lists are mutable.
Look at the built-in enumerate() function to get an idea how to iterate over the list and find each entry's index (which you can then use to assign to the specific list item).

Related

Getting sublist with repeated elements in Python [duplicate]

I faced some problem with solving the next problem:
We have a list of elements (integers), and we should return a list consisting of only the non-unique elements in this list. Without changing order of the list
I think the best way is to delete or remove all unique element.
Take note that I just start to learn python and would like only the simplest solutions.
Here is my code:
def checkio(data):
for i in data:
if data.count(i) == 1: #if element seen in the list just ones, we delet this el
ind = data.index(i)
del data[ind]
return data
Your function can be made to work by iterating over the list in reverse:
def checkio(data):
for index in range(len(data) - 1, -1, -1):
if data.count(data[index]) == 1:
del data[index]
return data
print(checkio([3, 3, 5, 8, 1, 4, 5, 2, 4, 4, 3, 0]))
[3, 3, 5, 4, 5, 4, 4, 3]
print(checkio([1, 2, 3, 4]))
[]
This works, because it only deletes numbers in the section of the list that has already been iterated over.
Just I used list Comprehensions.
def checkio(data):
a=[i for i in data if data.count(i)>1]
return a
print checkio([1,1,2,2,1,1,1,3,4,5,6,7,8])
You can implement a OrderedCounter, eg:
from collections import OrderedDict, Counter
class OrderedCounter(Counter, OrderedDict):
pass
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = [k for k, v in OrderedCounter(data).items() if v > 1]
# [1, 3, 2, 5]
So you count the occurrence of each value, then filter on if it has a frequency of more than one. Inheriting from OrderedDict means the order of the original elements is preserved.
Going by comments, you want all duplicated elements reserved, so you can pre-build a set of the duplicate entries, then re-iterate your original list, eg:
from collections import Counter
data = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
duplicates = {k for k, v in Counter(data).items() if v > 1}
result = [el for el in data if el in duplicates]
# [1, 3, 1, 2, 3, 5, 1, 5, 2]
Try this:
>>> a=[1,2,3,3,4,5,6,6,7,8,9,2,0,0]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[2, 3, 3, 6, 6, 2, 0, 0]
>>> a=[1, 2, 3, 1, 3]
>>> a=[i for i in a if a.count(i)>1]
>>> a
[1, 3, 1, 3]
>>> a=[1, 2, 3, 4, 5]
>>> a=[i for i in a if a.count(i)>1]
a
[]
def checkio(data):
lis = []
for i in data:
if data.count(i)>1:
lis.append(i)
print(lis)
checkio([1,2,3,3,2,1])
Yeah it's a bit late to contribute to this thread but just wanted to put it there on the net for anyone else use.
Following what you have started, iterating on the list of integers, but not counting or deleting elements, try just testing if the element has already been seen, append it to a list of duplicated elements:
def checkio(data):
elements = []
duplicates = []
for i in data:
if i not in elements:
elements.append(i)
else:
if i not in duplicates:
duplicates.append(i)
return duplicates
d = [1, 3, 1, 2, 3, 5, 8, 1, 5, 2]
print (checkio(d))
#[1, 3, 5, 2]
numbers = [1, 1, 1, 1, 3, 4, 9, 0, 1, 1, 1]
x=set(numbers)
print(x)
You can use the set key word too to get the desired solution.
I used an integer and bool to check every time the list was modified within a while loop.
rechecks = 1
runscan = True
while runscan == True:
for i in data:
if data.count(i) <2:
data.remove(i)
rechecks+=1
#need to double check now
if rechecks >0:
runscan = True
rechecks-=1
else:
runscan = False
return data
Would it not be easier to generate a new list?
def unique_list(lst):
new_list = []
for value in lst:
if value not in new_list:
new_list.append(value)
return new_list
lst = [1,2,3,1,4,5,1,6,2,3,7,8,9]
print(unique_list(lst))
Prints [1,2,3,4,5,6,7,8,9]

Python groupby to split list by delimiter

I am pretty new to Python (3.6) and struggling to understand itertools groupby.
I've got the following list containing integers:
list1 = [1, 2, 0, 2, 3, 0, 4, 5, 0]
But the list could also be much longer and the '0' doesn't have to appear after every pair of numbers. It can also be after 3, 4 or more numbers. My goal is to split this list into sublists where the '0' is used as a delimiter and doesn't appear in any of these sublists.
list2 = [[1, 2], [2, 3], [4, 5]]
A similar problem has been solved here already:
Python spliting a list based on a delimiter word
Answer 2 seemed to help me a lot but unfortunately it only gave me a TypeError.
import itertools as it
list1 = [1, 2, 0, 2, 3, 0, 4, 5, 0]
list2 = [list(group) for key, group in it.groupby(list1, lambda x: x == 0) if not key]
print(list2)
File "H:/Python/work/ps0001/example.py", line 13, in
list2 = [list(group) for key, group in it.groupby(list, lambda x: x == '0') if not key]
TypeError: 'list' object is not callable
I would appreciate any help and be very happy to finally understand groupby.
You were checking for "0" (str) but you only have 0 (int) in your list. Also, you were using list as a variable name for your first list, which is a keyword in Python.
from itertools import groupby
list1 = [1, 2, 0, 2, 7, 3, 0, 4, 5, 0]
list2 = [list(group) for key, group in groupby(list1, lambda x: x == 0) if not key]
print(list2)
This should give you:
[[1, 2], [2, 7, 3], [4, 5]]
In your code, you need to change lambda x: x == '0' to lambda x: x == 0, since your working with a list of int, not a list of str.
Since others have shown how to improve your solution with itertools.groupby, you can also do this task with no libraries:
>>> list1 = [1, 2, 0, 2, 3, 0, 4, 5, 0]
>>> zeroes = [-1] + [i for i, e in enumerate(list1) if e == 0]
>>> result = [list1[zeroes[i] + 1: zeroes[i + 1]] for i in range(len(zeroes) - 1)]
>>> print(result)
[[1, 2], [2, 3], [4, 5]]
You can use regex for this:
>>> import ast
>>> your_list = [1, 2, 0, 2, 3, 0, 4, 5, 0]
>>> a_list = str(your_list).replace(', 0,', '], [').replace(', 0]', ']')
>>> your_result = ast.literal_eval(a_list)
>>> your_result
([1, 2], [2, 3], [4, 5])
>>> your_result[0]
[1, 2]
>>>
Or a single line solution:
ast.literal_eval(str(your_list).replace(', 0,', '], [').replace(', 0]', ']'))
You could do that within a Loop as depicted in the commented Snippet below:
list1 = [1, 2, 0, 2, 3, 0, 4, 5, 0]
tmp,result = ([],[]) # tmp HOLDS A TEMPORAL LIST :: result => RESULT
for i in list1:
if not i:
# CURRENT VALUE IS 0 SO WE BUILD THE SUB-LIST
result.append(tmp)
# RE-INITIALIZE THE tmp VARIABLE
tmp = []
else:
# SINCE CURRENT VALUE IS NOT 0, WE POPULATE THE tmp LIST
tmp.append(i)
print(result) # [[1, 2], [2, 3], [4, 5]]
Effectively:
list1 = [1, 2, 0, 2, 3, 0, 4, 5, 0]
tmp,result = ([],[]) # HOLDS A TEMPORAL LIST
for i in list1:
if not i:
result.append(tmp); tmp = []
else:
tmp.append(i)
print(result) # [[1, 2], [2, 3], [4, 5]]
Use zip to return a tuple of lists and convert them to list later on
>>> a
[1, 2, 0, 2, 3, 0, 4, 5, 0]
>>> a[0::3]
[1, 2, 4]
>>> a[1::3]
[2, 3, 5]
>>> zip(a[0::3],a[1::3])
[(1, 2), (2, 3), (4, 5)]
>>> [list(i) for i in zip(a[0::3],a[1::3])]
[[1, 2], [2, 3], [4, 5]]
Try to use join and then split by 0
lst = [1, 2, 0, 2, 3, 0, 4, 5, 0]
lst_string = "".join([str(x) for x in lst])
lst2 = lst_string.split('0')
lst3 = [list(y) for y in lst2]
lst4 = [list(map(int, z)) for z in lst3]
print(lst4)
Running on my console:

Add element into list at even indexes [duplicate]

This question already has answers here:
python: most elegant way to intersperse a list with an element
(15 answers)
Closed 6 years ago.
I have a list like
[1, 2, 3, 4, 5]
and I want to add zeroes at odd indexes:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
My first thought was to create a list with zeroes and replace them with the values from the original list.
listOfZeros = [0] * (2*len(list)-1)
j = 0
for i in range(0, len(listOfZeros)):
if (i%2 == 0):
listOfZeros[i] = h_temp[j]
j += 1
This actually works, but I do dislike for loops and adding another counter j. Isn't there a better way by using slicing?
You can use insert(). Looking at your output, assuming you are not counting index 0 as even.
a = [1,2,3,4,5]
for x in range(len(a)):
a.insert(2*x+1, 0)
one way is by using zip:
a = [1, 2, 3, 4, 5]
d = [x for t in zip (a, [0] * len(a)) for x in t][:-1]
When you use zip, you create list of tuples.
a = [1,2,3,4,5]
b = [0,0,0,0,0]
c = zip(a,b)
#zip (a,b) creates [(1,0),(2,0),(3,0),(4,0),(5,0)]
Then you loop over the set of tuples to arrange them into list:
d = [x for t in c for x in t] #creates [1,0,2,0,3,0,4,0,5,0]
and cut the last element (since you end with 5)
[x for t in c for x in t][:-1] #take out the last 0
#resulting in [1,0,2,0,3,0,4,0,5]
then you are done.
You can do it with a generator:
def zero_on_odd(mylist):
for i in mylist:
yield i
yield 0
a = [1, 2, 3]
with_zeros = list(zero_on_odd(a))[:-1]
If you want to go functional...
from itertools import chain, repeat
_list = [1,2,3,4,5]
list(chain(*zip(_list, repeat(0))))[:-1]
# [1, 0, 2, 0, 3, 0, 4, 0, 5]
If you want to be silly...
[int(i) for i in '0'.join(str(i) for i in _list)]
# still [1, 0, 2, 0, 3, 0, 4, 0, 5]
Or, if you want to be functional AND silly...
map(int, '0'.join(map(str, _list)))
# really, it's still [1, 0, 2, 0, 3, 0, 4, 0, 5]
# except in Python 3.X, there it's a map object...
But, you should probably opt for one of the custom generator solutions.
For the fun of it, here is an itertools solution:
from itertools import islice, chain
data = [1,2,3,4,5]
print list(islice(chain.from_iterable((x, 0) for x in data), 0, 2 * len(data)-1))
Giving:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
Another zip way:
>>> li
[1, 2, 3, 4, 5]
>>> [e for t in zip(li,[0]*(len(li)-1)) for e in t]+[li[-1]]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
You can also use range and slice assignment:
>>> li=[1,2,3,4,5]
>>> for i in range(1,len(li)+len(li)-1, 2): li[i:i]=[0]
...
>>> li
[1, 0, 2, 0, 3, 0, 4, 0, 5]
And, a list comprehension:
>>> [li[i/2] if not i%2 else 0 for i in range(len(li)*2-1)]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
A hacky way:
>>> ls1 = [1, 2, 3, 4, 5]
>>> ls2 = []
>>> list(ls2.extend([n, 0]) for n in ls1)
[None, None, None, None, None]
>>> ls2
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0]

remove duplicate element from a list, but only those who has odd number of duplicates

I am trying remove duplicate elements from the list, whose number of duplicates is odd.
For example for the following list: [1, 2, 3, 3, 3, 5, 8, 1, 8] I have 1 duplicated 2 times, 3 duplicated 3 times, and 8 duplicated 2 times. So 1 and 8 should be out and instead of 3 elements of 3 I need to leave only 1.
This is what I came up with:
def remove_odd_duplicates(arr):
h = {}
for i in arr:
if i in h:
h[i] += 1
else:
h[i] = 1
arr = []
for i in h:
if h[i] % 2:
arr.append(i)
return arr
It returns everything correctly: [2, 3, 5], but I do believe that this can be written in a nicer way. Any ideas?
You can use collections.Counter and list comprehension, like this
data = [1, 2, 3, 3, 3, 5, 8, 1, 8]
from collections import Counter
print [item for item, count in Counter(data).items() if count % 2]
# [2, 3, 5]
The Counter gives a dictionary, with every element in the input iterable as the keys and their corresponding counts as the values. So, we iterate over that dict and check if the count is odd and filter only those items out.
Note: The complexity of this solution is still O(N), just like your original program.
If order doesn't matter:
>>> a = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> list(set([x for x in a if a.count(x)%2 == 1]))
[2, 3, 5]
The list comprehension [x for x in a if a.count(x)%2 == 1] returns only the elements which appear an odd number of times in the list. list(set(...)) is a common way of removing duplicate entries from a list.
you can possibly use scipy.stats.itemfreq:
>>> from scipy.stats import itemfreq
>>> xs = [1, 2, 3, 3, 3, 5, 8, 1, 8]
>>> ifreq = itemfreq(xs)
>>> ifreq
array([[1, 2],
[2, 1],
[3, 3],
[5, 1],
[8, 2]])
>>> i = ifreq[:, 1] % 2 != 0
>>> ifreq[i, 0]
array([2, 3, 5])

Access certain elements of a list

Can't figure out how to do this in a pretty way :
I have a list of n elements,
I want to access every m elements of the list.
For example : [1, 2, 3, 4, 5] and m = 2 would give
[2, 4]
I can do it simply with a loop, but ins't there a more "pythonic" way?
Thanks by advance !
EDIT :
Seems like I forgot something.
I want, not only get those values but modify them.
I tried slicing a[::2] = 3, but it doesn't work. . .
I'm searching for something similar
Slicing syntax does this for you:
>>> my_list = range(10)
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> my_list[::2]
[0, 2, 4, 6, 8]
>>> my_list[1::2]
[1, 3, 5, 7, 9]
Here's a way to wrap a list to get the original assignment behavior you wanted, but I'm not sure I'd recommend it:
class AssignableSlice(list):
def __setitem__(self, i, v):
if isinstance(i, slice):
for ii in xrange(*i.indices(len(self))):
self[ii] = v
else:
super(AssignableSlice, self).__setitem__(i, v)
a = AssignableSlice(range(10))
print a
a[::2] = 3
print a
a[1::3] = 99
print a
produces:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 1, 3, 3, 3, 5, 3, 7, 3, 9]
[3, 99, 3, 3, 99, 5, 3, 99, 3, 9]
Ned's answer shows how to use slices to access a portion of the list. You can also assign to a slice, but you need to assign a list to the slice, for example:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[::2]
[0, 2, 4]
>>> my_list[::2] = [0, 0, 0]
>>> my_list
[0, 1, 0, 3, 0]
Note that when the step in your slice is anything besides the default of 1 the list that you assign needs to be the same length, however with a default step you can actually change the size of the list with slice assignment:
>>> my_list = range(5)
>>> my_list
[0, 1, 2, 3, 4]
>>> my_list[:1]
[0]
>>> my_list[:1] = [4, 3, 2] # replace the first item with 3 new items
>>> my_list
[4, 3, 2, 1, 2, 3, 4]
>>> my_list[2:5]
[2, 1, 2]
>>> my_list[2:5] = [] # remove the middle three items from the list
>>> my_list
[4, 3, 3, 4]
I juste found a way to do what I want using slicing.
The following :
candidates[::2] = [1] * len(candidates[::2])
will replace every 2 elements of candidates by 1

Categories