So I've written a bit of code to stack integers in a list from the zeroth position. For some reason I cannot decipher, the while loop below is not being processed. I have followed all good style and syntax requirements that I know, and the while loop works when run by itself.
def row(line):
"""
Function that merges a single row or column.
"""
result_length = len(line)
print result_length
# Create a list of zeros the same length as the 'line' argument
pts_alloc = 0
dummy = 0
result = line
result[0:] = [pts_alloc for dummy in range(len(result))]
print result
#Iterate over the 'line' list looking for non-zero entries and
#stack them from 'result[0]'
line_count = 0
result_place = 0
while (line_count <= (len(line)-1)):
if (line[line_count] > 0):
result[result_place] = line[line_count]
print result
result_place += 1
line_count += 1
return result
print row([4, 0, 0, 5])
Is there a major error in this code that I've missed? Is there some syntax requirement that I am unaware of?
The problems seems to be this part:
result = line
result[0:] = [pts_alloc for dummy in range(len(result))]
By replacing a slice of result, with result = line, you are replacing that same slice in line, too, as result is just another reference to the same list, not a copy.
Since the slice is the entire list, anyway, just do:
result = [pts_alloc for dummy in range(len(result))]
Also, you are declaring a lot of unnecessary variables. You could shorten your code to this:
def row(line):
result = [0] * len(line)
result_place = 0
for x in line:
if x > 0:
result[result_place] = x
result_place += 1
return result
Or even this:
def row(line):
non_zero = [x for x in line if x > 0] # take non-zero values
return non_zero + [0] * (len(line) - len(non_zero)) # pad with zeros
Related
I tried to parse through a text file, and see the index of the character where the four characters before it are each different. Like this:
wxrgh
The h would be the marker, since it is after the four different digits, and the index would be 4. I would find the index by converting the text into an array, and it works for the test but not for the actually input. Does anyone know what is wrong.
def Repeat(x):
size = len(x)
repeated = []
for i in range(_size):
k = i + 1
for j in range(k, _size):
if x[i] == x[j] and x[i] not in repeated:
repeated.append(x[i])
return repeated
with open("input4.txt") as f:
text = f.read()
test_array = []
split_array = list(text)
woah = ""
for i in split_array:
first = split_array[split_array.index(i)]
second = split_array[split_array.index(i) + 1]
third = split_array[split_array.index(i) + 2]
fourth = split_array[split_array.index(i) + 3]
test_array.append(first)
test_array.append(second)
test_array.append(third)
test_array.append(fourth)
print(test_array)
if Repeat(test_array) != []:
test_array = []
else:
woah = split_array.index(i)
print(woah)
print(woah)
I tried a test document and unit tests but that still does not work
You can utilise a set to help you with this.
Read the entire file into a list (buffer). Iterate over the buffer starting at offset 4. Create a set of the 4 characters that precede the current position. If the length of the set is 4 (i.e., they're all different) and the character at the current position is not in the set then you've found the index you're interested in.
W = 4
with open('input4.txt') as data:
buffer = data.read()
for i in range(W, len(buffer)):
if len(s := set(buffer[i-W:i])) == W and buffer[i] not in s:
print(i)
Note:
If the input data are split over multiple lines you may want to remove newline characters.
You will need to be using Python 3.8+ to take advantage of the assignment expression (walrus operator)
I wrote a function and it does not end. Logically len(array) should be decreasing but it stuck in 227. I think numpy delete does not work properly or I made mistake somewhere??
def segmenting (file, threshold):
segments = []
check = True
count = 0
while check == True:
if len(file) <= 2:
check = False
sequence = []
ids = []
for i in range(1, len(file)):
vector = [file[i,1] - file[0,1] , file[i,2]- file[0,2] ]
magnitude = math.sqrt(vector[0]**2 + vector[1]**2)
print(i)
if magnitude <= threshold:
sequence.append(file[i])
ids.append(i)
if i == len(file) and len(sequence) == 0:
file = np.delete(file, 0 , axis = 0)
break
if len(ids) >0 and len(sequence)>0 :
segments.append(sequence)
file = np.delete(file, ids , axis = 0)
print('sequence after :',sequence)
sequence = []
ids = []
print(len(file))
return segments
The following (simplified) logic will never be executed
for i in range(1, len(file)):
if i == len(file):
file = np.delete(file, 0)
Without having a way to remove the first line of the file, you have no way to exhaust your array. This check is superfluous anyway since after each iteration you won't need the first line anymore.
As a first fix you can put the check outside the loop and only check whether you've found any matches
for i in range(1, len(file)):
...
if len(sequence) == 0:
file = np.delete(file, 0)
But that way you would have one iteration where you find (and remove) matches and then one more with no more matches where you then remove it. Therefore, as said above, you should always remove the first line after each iteration.
With more simplifications, your code can be reduced down to:
def segmenting(file, threshold):
segments = []
while len(file) > 2:
idx = np.sqrt(np.sum((file[1:,1:3] - file[0,1:3])**2, axis=1)) <= threshold
file = file[1:]
segments.append(list(file[idx]))
file = file[np.logical_not(idx)]
return segments
It's likely due to the fact you are removing element from file array within a for loop, and also trying to iterate over for loop using file array. Try iterate over a clean version of file array(no modification on it), and do the deletion on a copy of file array
For example, one possible solution is to fix this line
for i in range(1, len(file)):
Fix like below
N=len(file)
for i in range(1, N):
Also you could remove flag variable 'check' and replace with break statement
I can print the following list of lists fine, but when I append to an empty list, it skips the last on each iteration or gives me an index out of range error when I add one more.
This works:
ordered_results = []
temp = []
A = len(results[1])-2
i = 1
while i < len(results):
x = 0
y = 1
while x < A:
temp = [results[i][0], results[0][x], results[i][y]]
print(temp)
x+=1
y+=1
temp = [results[i][0], results[0][x], results[i][y]]
print(temp)
i+=1
ordered_results
Note: len(results[0]) = 240 and len(results[1] = 241
If you replace "print" with ordered_results.append(temp) it skips:
results[i][0], results[0][239], results[i][240]
each iteration.
(Note the code was expanded as I am messing around trying to figure this out, it was more compact before).
I am trying to append an element to a list within a list that has an incremented value each time:
def get_data(file):
matrix = [ ['one','two','three'] ] #list of lists
test_count = 0
line_count = 0 #keep track of which line we are on
for line in file:
if line.find('example') != -1: #test for example string
temp_a = re.findall(r"\'(.+?)\'",line)[0]
print matrix[test_count][0] #should print 'one'
matrix[test_count][0].insert(temp_a) #should insert temp_a instead of 'one'
test_count += 1 #go to next "new" list in the matrix
line_count += 1 #go to next line
What I want is the result of findall to go into temp_a and from there to insert it into index 0 of the first list within a list. Then the next time findall is true, I want to insert temp_a to index 0 of the second list.
For example if the first temp_a value is 9, I would like the first list in the matrix to be:
[ [9,y,z] ]
If on the second findall my temp_a is 4, I want the matrix to become:
[ [9,y,z], [4,y,z] ]
The above code is my best attempt so far.
I have 2 questions:
1) How can I initialize a 'list of lists' if the amount of lists isn't fixed?
2) The list ['one','two','three'] was to test with printing what is going on. If I try to print out matrix[test_count][0], I get an "index out of range" error, but the moment I change it to print out matrix[0][0] it prints 'one' correctly. Is there something with the scope that I'm missing here?
To answer your questions:
1) Like this: matrix = []
Simply put, this just creates an empty list that you can append anything you want into, including more lists. So matrix.append([1,2,3]) gives you a list like this: [[1,2,3]]
2) So you're index out of range error is coming from the fact that you're incrementing test_count to 1 but your matrix is remaining length of 1 (meaning it only has the 0 index) since you never append anything. In order to get the output that you want you're going to need to make a few changes:
def get_data(file):
example_list = ['one','two','three']
matrix = [] #list of lists
test_count = 0
line_count = 0 #keep track of which line we are on
for line in file:
if line.find('example') != -1: #test for example string
temp_a = re.findall(r"\'(.+?)\'",line)[0]
new_list = example_list[:]
new_list[0] = temp_a
matrix.append(new_list)
test_count += 1 #go to next "new" list in the matrix
line_count += 1 #go to next line
print matrix #[['boxes', 'two', 'three'], ['equilateral', 'two', 'three'], ['sphere', 'two', 'three']]
For 2), did you try to print out test_count? Since your test_count+=1 is in if statement, it shouldn't be out of range without printing "one".
For 1), you could do this before insert:
if test_count == len(matrix):
matrix.append([])
It adds a new empty list if test_count of out range of matrix.
EDIT:
"Out of range" caused by line temp_a = re.findall(r"\'(.+?)\'",line)[0] because it can't find anything. So it's an empty list, and [0] out of range.
def get_data(file):
matrix = [ ['one','two','three'] ] #list of lists
test_count = 0
line_count = 0 #keep track of which line we are on
for line in file:
if line.find('example') != -1: #test for example string
temp_a = re.findall(r"\'(.+?)\'",line)
if temp_a:
temp_a = temp_a[0]
else:
continue # do something if not found
print(matrix[test_count][0]) #should print 'one'
new_list = matrix[test_count][:]
new_list[0] = temp_a
matrix[test_count].append(new_list) #should insert temp_a instead of 'one'
test_count += 1 #go to next "new" list in the matrix
line_count += 1 #go to next line
t = 8
string = "1 2 3 4 3 3 2 1"
string.replace(" ","")
string2 = [x for x in string]
print string2
for n in range(t-1):
string2.remove(' ')
print string2
def remover(ca):
newca = []
print len(ca)
if len(ca) == 1:
return ca
else:
for i in ca:
newca.append(int(i) - int(min(ca)))
for x in newca:
if x == 0:
newca.remove(0)
print newca
return remover(newca)
print (remover(string2))
It's supposed to be a program that takes in a list of numbers, and for every number in the list it subtracts from it, the min(list). It works fine for the first few iterations but not towards the end. I've added print statements here and there to help out.
EDIT:
t = 8
string = "1 2 3 4 3 3 2 1"
string = string.replace(" ","")
string2 = [x for x in string]
print len(string2)
def remover(ca):
newca = []
if len(ca) == 1: return()
else:
for i in ca:
newca.append(int(i) - int(min(ca)))
while 0 in newca:
newca.remove(0)
print len(newca)
return remover(newca)
print (remover(string2))
for x in newca:
if x == 0:
newca.remove(0)
Iterating over a list and removing things from it at the same time can lead to strange and unexpected behvaior. Try using a while loop instead.
while 0 in newca:
newca.remove(0)
Or a list comprehension:
newca = [item for item in newca if item != 0]
Or create yet another temporary list:
newnewca = []
for x in newca:
if x != 0:
newnewca.append(x)
print newnewca
return remover(newnewca)
(Not a real answer, JFYI:)
Your program can be waaay shorter if you decompose it into proper parts.
def aboveMin(items):
min_value = min(items) # only calculate it once
return differenceWith(min_value, items)
def differenceWith(min_value, items):
result = []
for value in items:
result.append(value - min_value)
return result
The above pattern can, as usual, be replaced with a comprehension:
def differenceWith(min_value, items):
return [value - min_value for value in items]
Try it:
>>> print aboveMin([1, 2, 3, 4, 5])
[0, 1, 2, 3, 4]
Note how no item is ever removed, and that data are generally not mutated at all. This approach helps reason about programs a lot; try it.
So IF I've understood the description of what you expect,
I believe the script below would result in something closer to your goal.
Logic:
split will return an array composed of each "number" provided to raw_input, while even if you used the output of replace, you'd end up with a very long number (you took out the spaces that separated each number from one another), and your actual split of string splits it in single digits number, which does not match your described intent
you should test that each input provided is an integer
as you already do a print in your function, no need for it to return anything
avoid adding zeros to your new array, just test first
string = raw_input()
array = string.split()
intarray = []
for x in array:
try:
intarray.append(int(x))
except:
pass
def remover(arrayofint):
newarray = []
minimum = min(arrayofint)
for i in array:
if i > minimum:
newarray.append(i - minimum)
if len(newarray) > 0:
print newarray
remover(newarray)
remover(intarray)