I am trying to multiply some of the values of an array by 3, but when I print the array with its new values I see that the numbers have actually been multiplied by 2187 and not 3. Very strange.
for digit in digits:
digits[0] = digits[0]*3
digits[2] = digits[2]*3
digits[4] = digits[4]*3
digits[6] = digits[6]*3
The original numbers in the array are [1,2,3,4,5,6,7]
What they should be after being multiplied is:
[3,2,9,4,15,6,21]
Instead we get [2187,2,6561,4,10935,6,15309].
You are multiplying it everytime and hence the large numbers! The loop multiplies the values each time by 3.
Thus 1 will become 2187 which is 1*3*3*3*3*3*3*3
Either do it all at once (Remove the for loop)
>>> digits = [1,2,3,4,5,6,7]
>>> digits[0] = digits[0]*3
>>> digits[2] = digits[2]*3
>>> digits[4] = digits[4]*3
>>> digits[6] = digits[6]*3
>>> digits
[3, 2, 9, 4, 15, 6, 21]
Or use a condition in the loop
>>> digits = [1,2,3,4,5,6,7]
>>> for i, v in enumerate(digits):
... if(i % 2 == 0):
... digits[i] = v * 3
...
>>> digits
[3, 2, 9, 4, 15, 6, 21]
Here I have used enumerate which will return a tuple of index and values.
Or you can even use a range function with a step of 2
>>> digits = [1,2,3,4,5,6,7]
>>> for i in range(0, len(digits), 2):
... digits[i] = digits[i]*3
...
>>> digits
[3, 2, 9, 4, 15, 6, 21]
Just to demonstrate Python slicing and list comprehensions:
>>> L = [1,2,3,4,5,6,7]
>>> L[::2] = [x*3 for x in L[::2]]
>>> L
[3, 2, 9, 4, 15, 6, 21]
Select for replacement every other character with L[::2] =, then use a list comprehension to triple each of those entries in the list.
Related
I have a list of n numbers. I want to group them in g groups. Also, I want to reverse elements in every odd group. Finally, I would combine all elements in even and odd groups into a new sublist. First I am giving what answer I am expecting and where I went wrong:
Expected answer:
num = 14
grp = 4
# A list of num natural numbers arranged in group (row) of 4 numbers
lst =
[0,1,2,3,
4,5,6,7,
8,9,10,11,
12,13]
lst =
[[0,1,2,3],
[4,5,6,7],
[8,9,10,11],
[12,13]]
# Reverse elements in odd rows
newlst =
[[0,1,2,3],
[7,6,5,4], # reversed here
[8,9,10,11],
[13,12]] # reversed here
# combine elements in all sublists by their position
# combine first element in all sublists into a new sublist
sollst =
[[0,7,8,13],[1,6,9,12],[2,5,10],[3,4,11]]
My solution:
num = 14
grp = 4
#### print
lst= list(range(0,num,1))
newlst= [lst[i:i+grp:1] for i in range(0,num,grp)]
evnlst = newlst[0::2]
oddlst = newlst[1::2]
newoddlst = [oddlst [i][::-1] for i in range(len(oddlst))]
sollst= evnlst + newoddlst
# This gives [[0, 1, 2, 3], [8, 9, 10, 11], [7, 6, 5, 4], [13, 12]]
from itertools import zip_longest
print([[x for x in t if x is not None] for t in zip_longest(fevngps)])
Present answer:
I reached the one step before the final answer and now I have to combine the lists of different lengths and I am running into an error
TypeError: 'int' object is not subscriptable
One approach:
from itertools import zip_longest
num = 14
grp = 4
lst = list(range(0, num, 1))
newlst = [lst[i:i + grp:1] for i in range(0, num, grp)]
# build new list where the sub-list are reversed if in odd indices
revlst = [lst[::-1] if i % 2 == 1 else lst for i, lst in enumerate(newlst)]
# zip using zip_longest and filter out the None values (the default fill value of zip_longest)
result = [[v for v in vs if v is not None] for vs in zip_longest(*revlst)]
print(result)
Output
[[0, 7, 8, 13], [1, 6, 9, 12], [2, 5, 10], [3, 4, 11]]
Write a program with the definition of a function named Array_Swap() that will accept an integer list & its size as arguments and the function will swap elements in such a way that the first element is swapped with the last element, the second element is swapped with the second last element and so on, only if anyone or both the elements are odd and display the result.
If initially, a list of seven elements is: [5, 16, 4, 7, 19, 8, 2], the contents of the list after the execution should be:
[2, 16, 19, 7, 4, 8, 5].
def Array_Swap(List,Size):
for i in range (Size//2):
List[i]=List[Size//2-i]
print(List)
L=[]
n=int(input("Enter number of elements"))
for i in range(n):
x=int(input("Enter element"))
L.append(x)
Array_Swap(L,len(L))
The size/length of the list is not relevant because it can be obtained by len(list). And even then it's not required to conditionally swap items in the list. I suggest that the Size parameter be removed, but considering it's an assignment, it can be given a default of None so that it can be ignored by the caller if desired.
The following algorithm zips the input list with its reverse to form pairs relative to their index from the front and end of the list respectively, i.e. the first and last items are paired, the second and second last are paired, etc. Once the items are paired it is simply a matter of iterating over the list and emitting the second number of the pair if either number is odd, or the first number if neither is odd - effectively swapping the pairs as required.
This is done in-place (that's what the List[:] does) with a list comprehension.
def ArraySwap(List, Size=None):
List[:] = [b if (a % 2 or b % 2) else a
for a, b in zip(List, reversed(List))]
print(List)
>>> l = [5, 16, 4, 7, 19, 8, 2]
>>> ArraySwap(l)
[2, 16, 19, 7, 4, 8, 5]
>>> l
[2, 16, 19, 7, 4, 8, 5]
>>> l = list(range(1,30))
>>> ArraySwap(l)
[29, 2, 27, 4, 25, 6, 23, 8, 21, 10, 19, 12, 17, 14, 15, 16, 13, 18, 11, 20, 9, 22, 7, 24, 5, 26, 3, 28, 1]
>>> ArraySwap([1])
[1]
>>> ArraySwap([])
[]
To swap two elements in the list, use the pattern a, b = b, a.
If i is the index of a list item, it's opposite/mirror element is -(i+1), or - i - 1.
so for the 0th element (first one), the mirror is -(0+1), = -1
using that as the indexer for the element, swap the two list elements IF
check that at least one of them is odd before swapping:
def Array_Swap(List,Size):
for i in range (Size // 2):
if List[i] % 2 == 1 or List[-(i+1)] % 2 == 1:
List[i], List[-(i+1)] = List[-(i+1)], List[i]
print(List)
L = [5, 16, 4, 7, 19, 8, 2] # use your input blocks as before, this is an example
Array_Swap(L,len(L))
Output: [2, 16, 19, 7, 4, 8, 5]
(And if L = [5, 16, 4, 7, 19, 8, 1, 2], output is [2, 1, 4, 19, 7, 8, 16, 5].)
Btw, you don't need to pass in the size of the list as a parameter.
You could do just: for i in range(len(List) // 2)
Another solution:
def Array_Swap(List, Size=None):
if Size is None:
Size = len(List)
for (i, j) in zip(range(Size // 2), range(Size - 1, Size // 2, -1)):
if List[i] % 2 or List[j] % 2:
List[i], List[j] = List[j], List[i]
print(List)
Alternatively:
Size parameter is redundant since python's list instance knows its own size
Use bitwise operatos & | >>... possibly cheaper than modulus % and divide / operations.
def Array_Swap(List):
for i in range(len(List) >> 1):
if (List[i] | List[-i-1]) & 1:
List[i], List[-i-1] = List[-i-1], List[i]
print(List)
The standard way to swap two variables in Python is:
a, b = b, a
In this case, you would do:
lst[i], lst[size - i - 1] = lst[size - i - 1], lst[i]
which swaps the ith element with the element that is at index size - i - 1 (i.e. the ith index from the end).
The other issue with your code is that it doesn't check whether either of the elements being swapped are odd, which you can resolve by adding the condition:
if lst[i] % 2 or lst[size - i - 1] % 2:
before doing the swap. This uses the modulo operator (%) to check the parity of the elements. Taking a number modulo 2 will return 1 if the number is odd. If either are odd (1 has a truth value of True), the condition would succeed and the swap will be performed.
Finally, your function was printing the list, rather than returning it. Its usually best to return a result and print the returned result.
The full working version, with the above three changes is as follows:
def list_swap(lst, size):
for i in range(size // 2):
if lst[i] % 2 or lst[size - i - 1] % 2:
lst[i], lst[size - i - 1] = lst[size - i - 1], lst[i]
return lst
l = []
n = int(input("Enter number of elements: "))
for _ in range(n):
x = int(input("Enter element: "))
l.append(x)
result = list_swap(l, len(l))
print(result)
Also note, I've changed all the variables to be lowercase, which is standard in Python.
With your shown example:
Enter number of elements: 7
Enter element: 5
Enter element: 16
Enter element: 4
Enter element: 7
Enter element: 19
Enter element: 8
Enter element: 2
[2, 16, 19, 7, 4, 8, 5]
Here's basic problem:
>>> listb = [ 1, 2, 3, 4, 5, 6, 7 ]
>>> slicea = slice(2,5)
>>> listb[slicea]
[3, 4, 5]
>>> lista = listb[slicea]
>>> lista
[3, 4, 5]
>>> listb[slicea] += lista
>>> listb
[1, 2, 3, 4, 5, 3, 4, 5, 6, 7]
listb should be
[1, 2, 6, 8, 10, 6, 7]
But 3, 4, 5 was inserted after 3, 4, 5 not added to it.
tl;dr
I have this code that's not working:
self.lib_tree.item(song)['values'][select_values] = adj_list
self.lib_tree.item(album)['values'][select_values] += adj_list
self.lib_tree.item(artist)['values'][select_values] += adj_list
The full code is this:
def toggle_select(self, song, album, artist):
# 'values' 0=Access, 1=Size, 2=Selected Size, 3=StatTime, 4=StatSize,
# 5=Count, 6=Seconds, 7=SelSize, 8=SelCount, 9=SelSeconds
# Set slice to StatSize, Count, Seconds
total_values = slice(4, 7) # start at index, stop before index
select_values = slice(7, 10) # start at index, stop before index
tags = self.lib_tree.item(song)['tags']
if "songsel" in tags:
# We will toggle off and subtract from selected parent totals
tags.remove("songsel")
self.lib_tree.item(song, tags=(tags))
# Get StatSize, Count and Seconds
adj_list = [element * -1 for element in \
self.lib_tree.item(song)['values'][total_values]]
else:
tags.append("songsel")
self.lib_tree.item(song, tags=(tags))
# Get StatSize, Count and Seconds
adj_list = self.lib_tree.item(song)['values'][total_values] # 1 past
self.lib_tree.item(song)['values'][select_values] = adj_list
self.lib_tree.item(album)['values'][select_values] += adj_list
self.lib_tree.item(artist)['values'][select_values] += adj_list
if self.debug_toggle < 10:
self.debug_toggle += 1
print('artist,album,song:',self.lib_tree.item(artist, 'text'), \
self.lib_tree.item(album, 'text'), \
self.lib_tree.item(song, 'text'))
print('adj_list:',adj_list)
The adj_list has the correct values showing up in debug.
How do I add a list of values to the slice of a list?
The behavior you want is not a feature of any Python built-in type; + with built-in sequences means concatenation, not element-wise addition. But numpy arrays will do what you want, so I'd suggest looking into numpy. Simple example:
>>> import numpy as np
>>> a = np.array([2,3,4], dtype=np.int64)
>>> b = np.array([5,6,7], dtype=np.int64)
>>> a += b
>>> a
array([ 7, 9, 11])
>>> print(a)
[ 7 9 11]
>>> print(a.tolist())
[7, 9, 11]
Note that the output (both repr and str forms) looks a little different from Python lists, but you can convert back to a plain Python list if needed.
So I need to have a code that checks one integer, and checks if the integer after it is the same value. If so, it will add the value to x.
input1 = [int(i) for i in str(1234441122)]
x= 0
So my code currently gives the result [1, 2, 3, 4, 4, 4, 1, 1 ,2 ,2]. I want it to give the result of x = 0+4+4+1+2.
I do not know any way to do that.
The following will work. Zip together adjacent pairs and only take the first elements if they are the same as the second ones:
>>> lst = [1, 2, 3, 4, 4, 4, 1, 1, 2, 2]
>>> sum(x for x, y in zip(lst, lst[1:]) if x == y)
11
While this should be a little less [space-]efficent in theory (as the slice creates an extra list), it still has O(N) complexity in time and space and is well more readable than most solutions based on indexed access. A tricky way to avoid the slice while still being concise and avoiding any imports would be:
>>> sum((lst[i] == lst[i-1]) * lst[i] for i in range(1, len(lst))) # Py2: xrange
11
This makes use of the fact that lst[i]==lst[i-1] will be cast to 0 or 1 appropriately.
Another way using itertools.groupby
l = [1, 2, 3, 4, 4, 4, 1, 1 ,2 ,2]
from itertools import groupby
sum(sum(g)-k for k,g in groupby(l))
#11
You can try this:
s = str(1234441122)
new_data = [int(a) for i, a in enumerate(s) if i+1 < len(s) and a == s[i+1]]
print(new_data)
final_data = sum(new_data)
Output:
[4, 4, 1, 2]
11
No need for that list. You can remove the "non-repeated" digits from the string already:
>>> n = 1234441122
>>> import re
>>> sum(map(int, re.sub(r'(.)(?!\1)', '', str(n))))
11
You are simply iterating on string and converting character to integer. You need to iterate and compare to next character.
a = str(1234441122)
sum = 0
for i,j in enumerate(a[:-1]):
if a[i] == a[i+1]:
sum+=int(a[i])
print(sum)
Output
11
Try this one too:
input1 = [int(i) for i in str(1234441122)]
x= 0
res = [input1[i] for i in range(len(input1)-1) if input1[i+1]==input1[i]]
print(res)
print(sum(res))
Output:
[4, 4, 1, 2]
11
Here's a slightly more space efficient version of #schwobaseggl's answer.
>>> lst = [1, 2, 3, 4, 4, 4, 1, 1, 2, 2]
>>> it = iter(lst)
>>> next(it) # throw away first value
>>> sum(x for x,y in zip(lst, it) if x == y)
11
Alernatively, using an islice from the itertools module is equivalent but looks a bit nicer.
>>> from itertools import islice
>>> sum(x for x,y in zip(lst, islice(lst, 1, None, 1)) if x == y)
11
Given the following code:
length = 10
numbers = [x for x in range(length)]
start_index = randint(0,length-1)
# now output each value in order from start to start-1 (or end)
# ex. if start = 3 --> output = 3,4,5,6,7,8,9,0,1,2
# ex if start = 9 ---> output = 9,0,1,2,3,4,5,6,7,8
What is the best / simplest / most pythonic / coolest way to iterate over the list and print each value sequentially, beginning at start and wrapping to start-1 or the end if the random value were 0.
Ex. start = 3 then output = 3,4,5,6,7,8,9,1,2
I can think of some ugly ways (try, except IndexError for example) but looking for something better. Thanks!
EDIT: made it clearer that start is the index value to start at
You should use the % (modulo) operator.
length = 10
numbers = [x for x in range(length)]
start = randint(0, length)
for i in range(length):
n = numbers[(i + start) % length]
print(n)
>>> start = randint(0, len(numbers))
>>> start
1
You can use list slicing then iterate over that
>>> numbers[start:] + numbers[:start]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
You can also use the modulus % operator in a list comprehension
>>> [numbers[i%len(numbers)] for i in range(start, start + len(numbers))]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
What is the best / simplest / most pythonic / coolest way ...
You can use collections.deque and its rotate function, like this
>>> from collections import deque
>>> d = deque(numbers)
>>> d.rotate(-9)
>>> d
deque([9, 0, 1, 2, 3, 4, 5, 6, 7, 8])
>>>
>>> d = deque(numbers)
>>> d.rotate(-2)
>>> d
deque([2, 3, 4, 5, 6, 7, 8, 9, 0, 1])
You can try to iterate over the list with simple conditional loops
i = start
while(True):
print i,
if i==numbers[-1]: # If it's the last number
i=numbers[0]
else:
i += 1
if i==start: # One iteration is over
break
This will print 3 4 5 6 7 8 9 0 1 2