Python: sorting through a list - list

I have a 2D list:
[['Hard', '7', '27.00'], ['David', '4', '26.00'], ['Great', '2', '25.00']]
I want to print it out in alphabetical order based on the first index of each list. I have a variable called listName which stores the information as presented above. I have tried listName.sort() however, it does not sort in alphabetical order. Any suggestions?

You have to pass a key argument to sort(). This function will sort the elements (in your case, each element is a list) based on the first item (x[0]) of that element:
listName.sort(key = lambda x:x[0])
Note: This will sort the lists based on an ASCII comparison (please, correct me if I'm wrong), therefore, it will put uppercase before lowercase. For example:
listName = [['Hard', '7', '27.00'], ['David', '4', '26.00'], ['Great', '2', '25.00'], ['a', '3', '123']]
listName.sort(key = lambda x:x[0])
print(listName)
# [['David', '4', '26.00'], ['Great', '2', '25.00'], ['Hard', '7', '27.00'], ['a', '3', '123']]

Two more options:
# The data
listName = [['Hard', '7', '27.00'], ['David', '4', '26.00'], ['Great', '2', '25.00'], ['a', '3', '123']]
# Use first element for sorting using operator.itemgetter (like x[0])
from operator import itemgetter
sorted(listName, key=itemgetter(0))
# Use a function instead of a lambda (+ case insensitive sorting)
def get(x):
# return first element of sublist and convert to lowercase
return x[0].lower()
sorted(listName, key=get)
Lambdas and function are very similar:
lambda x: x[0]
def get(x): return x[0]
The difference is that functions have a name and lambdas are anonymous (unless stored in a variable). You must not use return in a lambda, its behavior is always like there is one.

Related

why does the last character disappear?

The file contents are:
min:1,2,3,4,5,6
max:1,2,3,4,5,6
avg:1,2,3,4,5,6
Code:
def avg_calc():
total = 0
nums_inLine = line[4: -1]
num_list = []
num_list = nums_inLine.split(',')
length = len(num_list)
print(num_list)
with open('input.txt', 'r', encoding='utf-8-sig') as in_file:
content = in_file.readlines()
for line in content:
if 'min' in line:
min_calc()
elif 'max' in line:
max_calc()
elif 'avg' in line:
avg_calc()
My problem is that the '6' in the third line disappears or replaced by a whitespace. Why does it do that?
Output:
['1', '2', '3', '4', '5', '']
final goal is to cast each element in the list to an int then perform calculations to calculate the average of the numbers.

Is there a succinct way to split this negative integer into a list of digits? (Python)

I can do this using an if statement but I feel like the code is too long for this simple operation.
num = -12345
-->inserts magical code<--
desired output
num_list = ['-1', '2', '3', '4', '5']
You can simply use .split("\\B")
So the magical code would be:
String[] num_list = Integer.toString(num).split("\\B");

Group repeating list objects with itertools.groupby()

I have a list, where I want to group the repeating objects into a single object in the new list. Basically, convert this:
s = ['0.352125', '1', '1', '1', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0.241041', '0.313429', '1', '1']
to this:
s_new = ['0.352125', '4*1','8*0', '0.241041', '0.313429','2*1']
I have tried itertools.groupby() function (python 2.7) as below:
from itertools import groupby
s_g = [list(g) for k, g in groupby(s)]
s_new = [', '.join('{}*{}'.format(sum(1 for _ in g), k) for k, g in groupby(s_g))]
As a result, I get:
s_new = ["1*['0.352125'], 1*['1', '1', '1', '1'], 1*['0', '0', '0', '0', '0', '0', '0', '0'], 1*['0.241041'], 1*['0.313429'], 1*['1', '1']"]
Apparently, this is not the list format I'm trying to get. Could someone please help me with this?
You unnecessarily applied groupby twice and there's also no reason to use str.join.
You can use the following list comprehension instead:
['%s*' % len(l) * (len(l) > 1) + k for k, g in groupby(s) for l in (list(g),)]

write a Python 3 list to .csv

I have a list that i need to write to a .csv Yes, i have done a LOT of looking around (of course i found this link which is close to the target, but misses my case) You see writerows is having all sorts of trouble with the delimiters/formatting in the .csv (the a gets separated from the 1 from the 7 etc etc)
My list looks like this:
buffer = [['a17', 'b17', 'c17', '8', 'e17', 'f17\n'], ['a24', 'b24', 'c24', '6', 'e24', 'f24\n'], ['a27', 'b27', 'c27', '9', 'e27', 'f27\n'], ['a18', 'b18', 'c18', '9', 'e18', 'f18\n'], ['a5', 'b5', 'c5', '5', 'e5', 'f5\n'], ['a20', 'b20', 'c20', '2', 'e20', 'f20\n'], ['a10', 'b10', 'c10', '1', 'e10', 'f10\n'], ['a3', 'b3', 'c3', '3', 'e3', 'f3\n'], ['a11', 'b11', 'c11', '2', 'e11', 'f11\n']]
I can see its like a list of lists so i tried for eachRow in buffer: then following on with a eachRow.split(',') but no good there either.
I just need to write to a .csv it should be easy right... what am i missing?
You can remove the \n string from your buffer like so. Also you have to add newline='' to the with statement in Python 3. See this answer for more detail.
import csv
buffer = [['a17', 'b17', 'c17', '8', 'e17', 'f17\n'],
['a24', 'b24', 'c24', '6', 'e24', 'f24\n'],
['a27', 'b27', 'c27', '9', 'e27', 'f27\n'],
['a18', 'b18', 'c18', '9', 'e18', 'f18\n'],
['a5', 'b5', 'c5', '5', 'e5', 'f5\n'],
['a20', 'b20', 'c20', '2', 'e20', 'f20\n'],
['a10', 'b10', 'c10', '1', 'e10', 'f10\n'],
['a3', 'b3', 'c3', '3', 'e3', 'f3\n'],
['a11', 'b11', 'c11', '2', 'e11', 'f11\n']]
for row_index, list in enumerate(buffer):
for column_index, string in enumerate(list):
buffer[row_index][column_index] = buffer[row_index][column_index].replace('\n', '')
with open('output.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerows(buffer)
import csv
with open('output.csv','w') as f:
writer = csv.writer(f)
writer.writerows(buffer)
Note that the last entry in each of your lists has a newline, so the csvwriter is correctly quoting the string so you end up with "f17\n" (in the first list as an example) which will look strangely formatted if you are not expecting a new line.

Creating Lists from CSV File in python 2.7 using two different read line commands

I am a newbie at Python 2.7 and used the following code to create the list of observations pulled from a csv file.
import csv
data = []
with open(datafile,'rb') as f:
for row in f:
g=row
data.append(g)
It produces the following list (after reading the first row):
['01/01/2005,01:00,0,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,3,E,9,3,E,9,8.0,A,7,6.0,A,7,87,A,7,1013,A,7,150,A,7,2.1,A,7,16100,A,7,77777,A,7,1.1,E,8,0.099,F,8,0.160,F,8,0,1,A,7']
But when I use the following code to read the csv file and create the list:
data = []
with open(datafile,'rb') as f:
r = csv.reader(f)
for row in f
data = [row for row in r]
I get a list that looks as follows (after reading the first row):
['01/01/2005', '01:00', '0', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '3', 'E', '9', '3', 'E', '9', '8.0', 'A', '7', '6.0', 'A', '7', '87', 'A', '7', '1013', 'A', '7', '150', 'A', '7', '2.1', 'A', '7', '16100', 'A', '7', '77777', 'A', '7', '1.1', 'E', '8', '0.099', 'F', '8', '0.160', 'F', '8', '0', '1', 'A', '7']
This also appears to be a list (with the key difference being the apostrophes around each item in the list instead of just at the beginning and the end).
Since both appear to be lists, why does the code that uses data.append not deliver a similar list?
Your first list has just one single element -- a string holding the entire line, inclusing all the commas.
>>> l1 =['01/01/2005,01:00,0,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,0,2,0,3,E,9,3,E,9,8.0,A,7,6.0,A,7,87,A,7,1013,A,7,150,A,7,2.1,A,7,16100,A,7,77777,A,7,1.1,E,8,0.099,F,8,0.160,F,8,0,1,A,7']
>>> len(l1)
1
In your second example, csv.reader splits this line into several elements and puts those into the list.
>>> l2 = ['01/01/2005', '01:00', '0', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '0', '2', '0', '3', 'E', '9', '3', 'E', '9', '8.0', 'A', '7', '6.0', 'A', '7', '87', 'A', '7', '1013', 'A', '7', '150', 'A', '7', '2.1', 'A', '7', '16100', 'A', '7', '77777', 'A', '7', '1.1', 'E', '8', '0.099', 'F', '8', '0.160', 'F', '8', '0', '1', 'A', '7']
>>> len(l2)
68
Also note that the loop in your second example is somewhat odd. I assume that this is not your actual code, since there's a syntax error in it. It should probably rather be:
r = csv.reader(f)
for row in r: # row in r, not row in f
data.append(row) # append row to data -> 2d-array of items in rows