python list of list comparing elements - python

I want to compare element of lists. I parsed data from a text file but I couldn't compare the lists.
These are the lists which I got after parsing a text file:
[['Detected', '1', '-9.5', 'S19960'],['Active', '3', '-14.3', 'S19966'],
['Detected', '10788', '-10.5', 'S19961']]
[['Active', '2', '-16.3', 'S15620'],['Monitored', '2', '-18.2', 'S15629'],
['Detected', '2', '-8.8', 'S1003H'], ['Detected', '2', '-10.3', 'S02965'],
['Detected', '2', '-6.3', 'S56615'], ['Detected', '2', '-20.8', 'S10105'],
['Active', '2', '-20.8', 'S06940'], ['Detected', '2', '-17.8', 'S52835'],
['Detected', '2', '-20.8', 'S5198E'], ['Detected', '2', '-21.2', 'S56749'],
['Serving', '2', '-12.2', 'S02035'], ['Monitored', '2', '-24.5', 'S04919']]
The code will find Detected elements and will check if -9.5 (the second elements of lists) is bigger than -12. If it's bigger it will check Active and Servings elements.
For example -9.5 > -14.3, if the difference is bigger than 3, the output will be for the first list:
S19960 > S19966 | S19961 > S19966
for the second list:
S1003H > S15620,S06940,S02035 | S56615 > S15620,S06940,S02035

Here's a working implementation, which first finds the indexes of the relevant Detected elements (with value bigger than -12) and of the elements to be compared (Active and Serving elements). It then uses those indexes to parse and compare values in the list and generate an output string:
def comparisonFromList(data):
# find indexes of Detected elements with value > -12
detected = [i for i in range(len(data)) if data[i][0] in ['Detected'] and float(data[i][2]) > -12]
# find indexes of Active and Serving elements
tocompare = [i for i in range(len(data)) if data[i][0] not in ['Detected','Monitored']]
output = ""
for i,detect in enumerate(detected):
if i > 0:
output += ' | '
output += data[detect][3];
output += ' > '
for j,compare in enumerate(tocompare):
if abs(float(data[detect][2]) - float(data[compare][2])) > 3:
if 0 < j:
output += ','
output += data[compare][3];
return output
Output (based on the two input lists you provided):
> print(comparisonFromList(list1))
S19960 > S19966 | S19961 > S19966
> print(comparisonFromList(list2))
S1003H > S15620,S06940,S02035 | S02965 > S15620,S06940 | S56615 > S15620,S06940,S02035
Demo: https://repl.it/#glhr/55562796

Related

How to reverse a list while preserving the last index?

How I can reverse all the items of a list except the last index?
Example:
aList = ['1', '2', 'STAY']
And I would want the result to be:
aList = ['2', '1', 'STAY']
Very simple with slicing:
aList = ['1', '2', '3', '4', 'STAY']
aList[:-1] = aList[-2::-1]
print(aList)
Output:
['4', '3', '2', '1', 'STAY']
Explanation:
aList[:-1] = aList[-2::-1]
^ ^ ^
| | |___Travel towards the beginning
| |
| Start from the second to last element
|
Assign from first to second to last element
You can do the following:
alist=['1','2','STAY'] # Your List
fix=alist[-1] # Declaring the last element in alist using negative index
del alist[-1] # Deleting last element
alist.reverse() # Reversing the remaining list
alist.append(fix) # Inserting the last element in alist
Print the list to get your required list.

looping over list and delete items in for loop

I have list which has more than 1000 elements
and i have a page where i must add those elements from the list but the thing is the page only accepts 40 entries at a time.
so what i am tring to do is grab 40 elements from the list then submit those elements to the page using for loop then delete these elements from the list and grab 40 elements again, i need to do this till all the elements from the list are submitted to the page.
this is what i have done so far and failed
mylist1 = ['1','2','3','4','5','6','7','8','9','10','10','11',]
def listget():
newlistget = [x for x in mylist1]
return newlistget
while True:
for x in listget():
for i in range(0,40):
#do stuff
mylist1.remove(mylist1[i])
if not listget():
break
You don't need to alter your initial data; instead, you can request successive chunks of a given size from it:
something like this:
In this example, if len(seq) is not a multiple of chunk_size, the last values will be what's left in the sequence.
The keyword argument start can optionally be set to start the chunks at an arbitrary location.
def chunks(seq, chunk_size, start=0):
while start < len(seq):
end = chunk_size + start
yield(seq[start: end])
start = end
if __name__ == '__main__':
mylist = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '10', '11', ]
for chunk in chunks(mylist, 3):
print(chunk)
output:
['1', '2', '3']
['4', '5', '6']
['7', '8', '9']
['10', '10', '11']
Why can't you slice the list every time, because remove will be a costly operation
list1=[i for i in range(1234)] #some huge list
print(len(list1)) #1234
j=40
while(j<len(list1)):
new_list=list1[j-40:j] #slice the list for 40 elements
print(len(new_list))
''' add your processing here (like submitting)'''
j+=40
new_list=list1[j-40:] #the last part of the list
print(len(new_list))
A generalized version to break a list into even sized chunks :
n=40 #In this case
new_list = [my_list[i * n:(i + 1) * n] for i in range((len(my_list) + n - 1) // n )]
new_list is a list of lists with each list of size 40 (Maybe except the last one)
Even tho i don't fully understand the question, but i can do something that creates a list of list containing each forty elemnts, like:
print([mylist1[i:i+40] for i in range(0,len(mylist1),40)])
Demo:
mylist1 = list(range(1000))
print([mylist1[i:i+40] for i in range(0,len(mylist1),40)])

Python: Inserting into a list using length as index

All,
I've recently picked up Python and currently in the process of dealing with lists. I'm using a test file containing several lines of characters indented by a tab and then passing this into my python program.
The aim of my python script is to insert each line into a list using the length as the index which means that the list would be automatically sorted. I am considering the most basic case and am not concerned about any complex cases.
My python code below;
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList.insert(size, data)
for i in range(len(newList)):
print ( newList[i])
My 'test' file below;
2 2 2 2
1
3 2
2 3 3 3 3
3 3 3
My expectation of the output of the python script is to print the contents of the list in the following order sorted by length;
['1']
['3', '2']
['3', '3', '3']
['2', '2', '2', '2']
['2', '3', '3', '3', '3']
However, when I pass in my test file to my python script, I get the following;
cat test | ./listSort.py
['2', '2', '2', '2']
['1']
['3', '2']
['3', '3', '3']
['2', '3', '3', '3', '3']
The first line of the output ['2', '2', '2', '2'] is incorrect. I'm trying to figure out why it isn't being printed at the 4th line (because of length 4 which would mean that it would have been inserted into the 4th index of the list). Could someone please provide some insight into why this is? My understanding is that I am inserting each 'data' into the list using 'size' as the index which means when I print out the contents of the list, they would be printed in sorted order.
Thanks in advance!
Inserting into lists work quite differently than what you think:
>>> newList = []
>>> newList.insert(4, 4)
>>> newList
[4]
>>> newList.insert(1, 1)
>>> newList
[4, 1]
>>> newList.insert(2, 2)
>>> newList
[4, 1, 2]
>>> newList.insert(5, 5)
>>> newList
[4, 1, 2, 5]
>>> newList.insert(3, 3)
>>> newList
[4, 1, 2, 3, 5]
>>> newList.insert(0, 0)
>>> newList
[0, 4, 1, 2, 3, 5]
Hopefully you can see two things from this example:
The list indices are 0-based. That is to say, the first entry has index 0, the second has index 1, etc.
list.insert(idx, val) inserts things into the position which currently has index idx, and bumps everything after that down a position. If idx is larger than the current length of the list, the new item is silently added in the last position.
There are several ways to implement the functionality you want:
If you can predict the number of lines, you can allocate the list beforehand, and simply assign to the elements of the list instead of inserting:
newList = [None] * 5
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
If you can predict a reasonable upper bound of the number of lines, you can also do this, but you need to have some way to remove the None entries afterwards.
Use a dictionary:
newList = {}
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
Add elements to the list as necessary, which is probably a little bit more involved:
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
size = len(data)
if len(newList) < size: newList.extend([None] * (size - len(newList)))
newList[size - 1] = data
for i in range(len(newList)):
print ( newList[i])
I believe I've figured out the answer to my question, thanks to mkrieger1. I append to the list and then sort it using the length as the key;
newList = []
for line in sys.stdin:
data = line.strip().split('\t')
newList.append(data)
newList.sort(key=len)
for i in range(len(newList)):
print (newList[i])
I got the output I wanted;
/listSort.py < test
['1']
['3', '2']
['3', '3', '3']
['2', '2', '2', '2']
['2', '3', '3', '3', '3']

Counting the number of consecutive 3s in a 2D list

My dataset which I imported into python as a list:
Is there a way I can count the largest number of consecutive 3s? Like in the first row, the output should be 5 as there are 5 consecutive 3s.
import csv
r = csv.reader(open('motor.csv'))
list_r = list(r)
for row in list_r:
print
count = 0
for col in row:
if col == '3' and row[row.index(col)+1] == '3':
count+=1
print count
This is the code I wrote but I seem to get incorrect output.
Consider using itertools.groupby to break the list into sub-sequences of identical values. Then simply return the maximum length of the sub-sequences.
from itertools import groupby
list_r = [
['3','3','3','3','3','1','3','3','5'],
['1','2','3','3','3','3','3','3','1','3','3','5','3'],
['3','2','3','3','3','3','3','3','1','3','3','5'],
]
result = [
max(len(list(g)) for k, g in groupby(row) if k == '3')
for row in list_r
]
assert result == [5, 6, 6]
They to use the following as a guide:
import itertools
def consecutive(group):
first, second = itertools.tee(group)
second.next()
for first, second in itertools.izip(first, second):
if second != first + 1: return False
return True
def iterate_submatrix(matrix, t, l):
'''yield the horizontals and diagonals of 4x4 subsection of matrix starting at t(op), l(eft) as 4-tuples'''
submat = [row[l:l+4] for row in matrix[t:t+4]]
for r in submat: yield tuple(r)
for c in range (0,4):
yield tuple(r[c] for r in submat)
yield tuple(submat[rc][rc] for rc in range (0,4))
yield tuple(submat[rc][3-rc] for rc in range(0,4))
for item in iterate_submatrix(test_matrix, 0,0):
print item, consecutive(item)
First, row.index(col) will always produce the index of the first value of col in the row. This is clearly not what was intended. Instead, I'd recommend using enumerate to iterate over the values and indices in the row at the same time.
Second, you are only tracking the current number of consecutive 3's, and there is no code to track the maximum of this count value. Adding another variable and an else clause to your code can resolve this.
for row in list_r:
max_count = current_count = 0
for index, value in enumerate(row[:-1]):
if value == '3' and row[index+1] == '3':
current_count += 1
else:
max_count = max(current_count, max_count)
current_count = 0
print count
import re
data = [
['1', '2', '2', '3', '5', '6'],
['1', '2', '3', '3', '4', '5'],
['1', '2', '3', '3', '3', '4']
]
max = 0
for item in data:
match = re.search(r'3+', "".join(item))
try:
if len(str(match.group(0))) > max:
max = len(str(match.group(0)))
except AttributeError:
pass
print(max)

how to remove the first occurence of an integer in a list

this is my code:
positions = []
for i in lines[2]:
if i not in positions:
positions.append(i)
print (positions)
print (lines[1])
print (lines[2])
the output is:
['1', '2', '3', '4', '5']
['is', 'the', 'time', 'this', 'ends']
['1', '2', '3', '4', '1', '5']
I would want my output of the variable "positions" to be; ['2','3','4','1','5']
so instead of removing the second duplicate from the variable "lines[2]" it should remove the first duplicate.
You can reverse your list, create the positions and then reverse it back as mentioned by #tobias_k in the comment:
lst = ['1', '2', '3', '4', '1', '5']
positions = []
for i in reversed(lst):
if i not in positions:
positions.append(i)
list(reversed(positions))
# ['2', '3', '4', '1', '5']
You'll need to first detect what values are duplicated before you can build positions. Use an itertools.Counter() object to test if a value has been seen more than once:
from itertools import Counter
counts = Counter(lines[2])
positions = []
for i in lines[2]:
counts[i] -= 1
if counts[i] == 0:
# only add if this is the 'last' value
positions.append(i)
This'll work for any number of repetitions of values; only the last value to appear is ever used.
You could also reverse the list, and track what you have already seen with a set, which is faster than testing against the list:
positions = []
seen = set()
for i in reversed(lines[2]):
if i not in seen:
# only add if this is the first time we see the value
positions.append(i)
seen.add(i)
positions = positions[::-1] # reverse the output list
Both approaches require two iterations; the first to create the counts mapping, the second to reverse the output list. Which is faster will depend on the size of lines[2] and the number of duplicates in it, and wether or not you are using Python 3 (where Counter performance was significantly improved).
you can use a dictionary to save the last position of the element and then build a new list with that information
>>> data=['1', '2', '3', '4', '1', '5']
>>> temp={ e:i for i,e in enumerate(data) }
>>> sorted(temp, key=lambda x:temp[x])
['2', '3', '4', '1', '5']
>>>

Categories