Repeat values in array until specific length [duplicate] - python

This question already has answers here:
How to replicate array to specific length array
(4 answers)
Closed 2 years ago.
I need some kind of function or little tip for my problem.
So I got a list let's say
[1,2,3,4]
but I need this array to be longer with the same elements repeated so let's say I need an array of length 10 so it becomes:
[1,2,3,4,1,2,3,4,1,2]
So I need to extend the list with the same values as in the list in the same order
returnString = the array or string to return with extended elements
array = the basic array which needs to be extended
length = desired length
EDIT:
returnString = ""
array = list(array)
index = 0
while len(str(array)) != length:
if index <= length:
returnString += array[index]
index += 1
else:
toPut = index % length
returnString.append(array[toPut])
index += 1
return returnString

This is simple with itertools.cycle and itertools.islice:
from itertools import cycle, islice
input = [1, 2, 3, 4]
output = list(islice(cycle(input), 10))
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]

You can use itertools.cycle to iterate repeatedly over the list, and take as many values as you want.
from itertools import cycle
lst = [1, 2, 3, 4]
myiter = cycle(lst)
print([next(myiter) for _ in range(10)])
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]
You can also use it to extend the list (it doesn't matter if you append to the end while you are iterating over it, although removing items would not work).
from itertools import cycle
lst = [1, 2, 3, 4]
myiter = cycle(lst)
for _ in range(6):
lst.append(next(myiter))
print(lst)
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]

One way could be:
Iterate over the desired length - len(x_lst), So you have 10 - 4 = 6 (new elements to be added). Now since the list element should repeat, you can append the x_lst elements on the go by the indices (0,1,2,3,4,5).
x = [1,2,3,4]
length = 10
for i in range(length - len(x)):
x.append(x[i])
print(x)
OUTPUT:
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]

Try this:
n = 10
lst =[1,2,3,4]
new_lst = [lst[i%len(lst)] for i in range(n)]
print(new_lst)
Output:
[1, 2, 3, 4, 1, 2, 3, 4, 1, 2]

I will show a tip to you:
If you have this array [1,2,3,4] so you can create a separated newArray that get this value and fill the newArray with this repeated values.
How? Loop! I think for can do this to you, just point the array and newArray to it knows which it will fill.

NumOfValues = int(input("Number of Values: "))
List1 = [1,2,3,4]
List2 = []
Count = 0
while len(List2) < NumOfValues:
List2.append(List1[Count])
Count += 1
if Count > len(List1) - 1:
Count = 0
print(List2)

First multiply the list by the number of times it needs to be repeated. If that's not the desired length, extend it with the appropriate slice of the list.
old_len = len(original)
new_len = 10
result = original * new_len // old_len
if new_len % old_len != 0:
result += original[:new_len % old_len]

Related

Fill lists in list with zeros if their length less than

I have a list of lists with different sizes but I want to make them all the same length. For example, make them with length of 5 by padding with zeros if length less than 5 or cut the list if length is more than 5. For example, I have a list:
foo = [
[1, 2, 3],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5, 6, 7]]
result = [
[1, 2, 3, 0, 0],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]]
Do you have an idea of optimal and fast solution, if the list of lists is large?
List comprehension
Make a fill list and use slicing to get the appropriate lengths.
n = 5
fill = [0] * n
result = [sublist[:n] + fill[len(sublist):] for sublist in foo]
result = []
for sublist in foo:
size = len(sublist)
result.append(sublist[:5] + [0]*(5 - size))
To perform this optimization, i sliced additional elements beyond n = 5, and replaced with 0 those not reaching n = 5 by checking how many elements they miss.
def listOptimization(foo, n):
# slicing foo to have n elements on all child elements of foo
for i in range(len(foo)):
foo[i] = foo[i][:n]
# optimizing
for i in range(len(foo)):
# check if foo child element is less than n
# if true, append to the list with 0 depending on how many
# elements to reach n
if len(foo[i])<n:
temp = n-len(foo[i])
for x in range(temp):
foo[i].append(0)
return foo
result = [[bar[i] if i<len(bar)else 0 for i in range(5)] for bar in foo]
there are 5 elements in a row, so for i in range(5), the exceed 5 will be discard. then assign value directly,if the length of each row is less than i, assign 0
Actually, I found a pretty fast solution for me. If you have an idea how to solve it without a for loop please post.
for row in foo:
while len(row) < 5:
row.append(0)
else:
row[:5]

How to remove specific elements from python list and add those elements into last of the list?

There are many solution available on internet for the above question but i am building my own logic here and have written below solution so far but my code is not dynamic e.g my code is only working for num = 2.
How can we write code for dynamic user input using below logic. Any suggestion will be appreciated.
My Code:
l = [1,2,3,4,5,6,7]
l1 = []
num = 2
print('original list is:', l)
for i in range(0,num-1):
rem = l.pop(i)
l1.append(rem)
for i in range(0,num-1):
rem = l.pop(i)
l1.append(rem)
print('poup list is',l1)
l.extend(l1)
print('reverse list is',l)
My Output: (when num = 2)
original list is: [1, 2, 3, 4, 5, 6, 7]
poup list is [1, 2]
reverse list is [3, 4, 5, 6, 7, 1, 2]
My Output: (when num = 3)
original list is: [1, 2, 3, 4, 5, 6, 7]
poup list is [1, 3, 2, 5]
reverse list is [4, 6, 7, 1, 3, 2, 5]
Expected Solution:
l = [1,2,3,4,5,6,7]
num = 2 (This number can be dynamic, User can pass any number)
Output: l = [3,4,5,6,7,1,2]
If user passed num = 3 then output should be like below:
Output: l = [4,5,6,7,1,2,3]
Even though the poup list and reverse list doesn't seem to represent the lists with the best names, the following code snippet should solve your problem:
l = [1,2,3,4,5,6,7]
print("Original list: {}".format(l) )
num = input("Enter value of 'num': " )
l1 = []
for i in range(0,int(num)):
rem = l.pop(0)
l1.append(rem)
print('poup list is',l1)
l.extend(l1)
print('reverse list is',l)
Here num is dynamically stored. The only minor correction to your for loop is that l should always pop the first element. This is because once an element is popped, the second element becomes the first element of your list. But due to incrementation in the value of i, it just skips that element.
Here's a sample output:
Original list: [1, 2, 3, 4, 5, 6, 7]
Enter value of 'num': 4
poup list is [1, 2, 3, 4]
reverse list is [5, 6, 7, 1, 2, 3, 4]
​
You could use a while loop. Problem with your code is that index positions changed when popping, in case of num = 2 it was fine, but then it messed up with new positions.
l = [1,2,3,4,5,6,7]
l1 = []
num = 3
print('original list is:', l)
y = 0
while y != num:
rem = l.pop(0)
y +=1
l1.append(rem)
print(l)
print('poup list is',l1)
l.extend(l1)
print('reverse list is',l)

Count number of element in a array that is less than the element in another array

I am not sure whether this is the right place to ask this question, but I am struggling to get to the right answer myself. I have done a programming test and I can not figure why my code fails in certain test cases.
The problem is that given an unsorted array of elements, e.g [1, 4, 2, 4] and an array of maximum, e.g [3,5], gives the solution of the count of elements in the first array that is less than the maximums in the second array. i.e [2, 4]
some example would be
inputs
nums = [2, 10, 5, 4, 8]
maxes = [3, 1, 7, 8]
outputs
solution = [1, 0, 3, 4]
inputs
nums = [1, 4, 2, 4]
maxes = [3, 5]
outputs
solution = [2, 4]
since there is one element is that is less than or equal to 3, and 0 element that is less than or equal to 1 and 3 element that is less than or equal to 3 and 4 element that is less than or equal to 8
Pseudocode:
Sort number array
Sort maximum array
create a list counts
for max elem in max array
find first elem in number array that is greater than or
equal to max elem and save its (index+1) in counts
So now counts will be a parallel array to the sorted number array. At index 0 of counts we have the number of elements smaller than the number at index 0 of max array.
You can do the below if you need your data in a dictionary form (as you did in your solution) as opposed to two parallel lists.
Set index to 0
for max elem in max array:
dictionary[max elem] = counts[index]
index += 1
Note you can use enumerate above but I wasn't sure you knew about it yet so I tried to give the simplest solution.
Here's a simplified version of what you need to do
nums = [1, 4, 2, 4]
maxes = [3,5]
result = [0]*len(maxes)
for index, max_val in enumerate(maxes):
for num in nums:
if num <= max_val:
result[index] += 1
print(result)
I'd just write this as
[sum(1 for x in nums if x < m) for m in maxes]
Demo:
>>> nums = [2, 10, 5, 4, 8]
>>> maxes = [3, 1, 7, 8]
>>>
>>> [sum(1 for x in nums if x < m) for m in maxes]
[1, 0, 3, 3]
>>>
>>> nums = [1, 4, 2, 4]
>>> maxes = [3, 5]
>>>
>>> [sum(1 for x in nums if x < m) for m in maxes]
[2, 4]
It's readable, memory efficient, uses fast comprehensions implemented in C and you would have to work hard to find an example where further microoptimizations are justified.
def find_total_matches(team_a, team_b):
if not team_b:
return []
if not team_a:
return [0]*len(team_b)
team_a.sort()
team_b_sorted = sorted(team_b)
a_i = 0
b_i = 0
c_sum = 0
cnt = dict()
while a_i <len(team_a) and b_i < len(team_b_sorted):
val= team_b_sorted [b_i]
if val not in cnt:
while a_i < len(team_a) and val >= team_a[a_i]:
c_sum += 1
a_i += 1
cnt[val] = c_sum
b_i += 1
result = []
for val in team_b:
result.append(cnt[val])
return result

Advanced list comprehension

A list of ints is entered into the program 1 at a time, for example:
[1, 3, 1, 4, 4, 3, 1]
Task:
Print a list that contains exactly the same numbers as the given list,
but rearranged so that every 3 is immediately followed by a 4. The 3's must not move index places, but every other number may move.
The output of the example should read:
[1, 3, 4, 1, 1, 3, 4]
My code so far is only able to complete the rules 1 and 2. How could my code be modified to cater to this?
newList=[]
n=0
numCount= int(input())
while True:
try:
n = int(input())
except:
break
if len(newList) !=(numCount):
if n == 3:
newList.append(3)
newList.append(4)
else:
newList.append(n)
print(newList)
I suggest you to first get all the indexes of 3 and 4 in the input list, then swap each element following a 3 with a 4. It gives the following code, which is quite short and easily readable:
a = [1, 3, 1, 4, 4, 3, 1]
# Get the indexes of 3 and 4 in the list
indexesOf3 = [i for i,elem in enumerate(a) if elem == 3]
indexesOf4 = [i for i,elem in enumerate(a) if elem == 4]
# Swap each element following a 3 with a 4
for i3,i4 in zip(indexesOf3,indexesOf4):
a[i3+1], a[i4] = a[i4], a[i3+1]
print(a)
# [1, 3, 4, 1, 1, 3, 4]
Note: this code example modifies the input list, but obviously it can be easily updated into a function returning a new list and keeping the input list as it is.
Here is a function doing exactly that:
def arrange_list(my_list):
# Copy the whole list
arranged_list=myList.copy()
# Find the all 4s
index_of_4s=[i for i, x in enumerate(arranged_list) if x == 4]
next_4=0
# Loop over the whole list
for i in range(len(arrangedList)):
if(arrangedList[i]==3): # We only care about 3s
# We swap the previously found 4 with a 1
arranged_list[index_of_4s[next_4]]=arranged_list[i+1]
arranged_list[i+1]=4
# We target the next 4
next_4=next_4+1
return arranged_list
If we test it with your example we get:
myList=[1, 3, 1, 4, 4, 3, 1]
arrange_list(myList)
#> [1, 3, 4, 1, 1, 3, 4]
You're question is not really well defined, and a lost of scenario are not taken into account. This code does the work quite simply, the idea is to create a new list.
-Find the position of the 3 in the input
-Place the 3, followed by a 4 in the new list
-Place the remaining elements.
input_list = [1, 3, 1, 4, 4, 3, 1]
# Check the number of 3 and 4
n3 = input_list.count(3)
n4 = input_list.count(4)
if n3 > n4:
for i in range(n3-n4):
input_list.append(4)
elif n4 > n3:
for i in range(n4-n3):
input_list.append(3)
# Now let's look at the order. The 3 should not move and must be followed by a 4.
# Easy way, create a new list.
output_list = [None for i in range(len(input_list))]
# Then I'm using numpy to go faster but the idea is just to extract the ids are which the 3 are placed.
import numpy as np
# Place the 3 and the 4
for elt_3 in np.where(np.asarray(input_list) == 3)[0]:
output_list[elt_3] = 3
output_list[elt_3+1] = 4 # Must be sure that the input_list does not end by a 3 !!!
# Then we don't care of the position for the other numbers.
other_numbers = [x for x in input_list if x != 3 and x != 4]
for i, elt in enumerate(output_list):
if elt is None:
output_list[i] = other_numbers[0]
del other_numbers[0]
print (output_list)
In a more compact version with a single loop, it gives:
input_list = [1, 3, 1, 4, 4, 3, 1]
position_3 = np.where(np.asarray(input_list) == 3)[0]
other_numbers = [x for x in input_list if x != 3 and x != 4] # Not 3 and not 4
output_list = [None for i in range(len(input_list))]
for i, elt in enumerate(output_list):
if elt == 4:
continue
elif i not in position_3:
output_list[i] = other_numbers[0]
del other_numbers[0]
else:
output_list[i] = 3
output_list[i+1] = 4

Python check next three elements in list [duplicate]

This question already has answers here:
Check for presence of a sliced list in Python
(11 answers)
Closed 9 years ago.
I am not sure if this question has been asked before but I couldn't find anything similar from the question list. I would like to check if a list has a set of three values in a certain order. For example, I would like to check if an int list has a set of values 1, 2, 3 anywhere within that list. The length of the list is unknown and the list cannot be sorted.
Example:
Values to check: 1, 2, 3 (in this order)
Example of a list = [1, 1, 2, 3, 1]
This is what I have tried so far.
list1 = [1, 1, 2, 3, 1]
list2 = [1, 1, 4, 3, 1, 2, 1]
def checkValue:
for i in range (0, len(nums)):
if (nums[i+2] - nums[i+1] == nums[i+1] - nums[i]) == 1:
return True
return False
list1 --> return True
list2 ---> IndexError: list index out of range
EDIT: Thanks to those who answered and thank you for the list to the sublist question. I never thought that the set of integers can be considered as a sublist and use it to compare to a larger list.
It looks like you're searching a sequence in a list.
You can just compare parts of the list with the sequence.
def find_sequence_in_list(list_to_check, values):
for i in range (len(list_to_check) - len(values) + 1):
#print(list_to_check[i:i + len(values)])
if list_to_check[i:i + len(values)] == values:
return True
return False
values = [1, 2, 3]
data1 = [1, 1, 2, 3, 1]
data2 = [1, 1, 4, 3, 1, 2, 1]
print(find_sequence_in_list(data1, values))
print(find_sequence_in_list(data2, values))
Uncomment the print to see what's happening.
i + 2 is too large in the loop body, nums doesn't have that many elements. Fix it like this:
if i + 2 < len(nums) and (nums[i+2] - nums[i+1] == nums[i+1] - nums[i]) == 1:
...
You can use tuple comparison directly, along with zip iteration (or itertools.izip if you prefer, for general iterables):
>>> def findin(values, nums):
... t = tuple(values)
... return any(T == t for T in zip(*(nums[i:] for i in xrange(values))))
Which gives for your examples:
>>> findin([1,2,3], [1,1,2,3,1])
True
>>> findin([1,2,3], [1, 1, 4, 3, 1, 2, 1])
False
I'm thinking of using deque to the sublist comparison.
from collections import deque
def has_sublist(lst, sub):
tmp_q = deque([], maxlen=len(sub))
sub_q = deque(sub)
for i in nums:
if tmp_q == sub_q:
return True
else:
tmp_q.append(i)
return tmp_q == sub_q
The tmp_q has a max length of len(sub) (which is 3 in your example), it contains a sublist of list to search in.
Let's check if it works well:
>>> lst = [1, 1, 4, 3, 1, 2, 1]
>>> sub = [1, 2, 3]
>>> print has_sublist(lst, sub)
False
>>> lst = [1, 1, 4, 3, 1, 2, 3]
>>> print has_sublist(lst, sub)
True
>>> lst = [1, 2]
>>> print find(lst, sub)
False
>>> lst = [1, 2, 3]
>>> print has_sublist(lst, sub)
True
In this case, you have no need to worry about the IndexError.

Categories

Resources