Sorted dicts lists manual changing - django

In my views I have a dict list such as
data = [{'name': 'Abe', 'seq': [4, 3]}, {'name': 'All names', 'seq': [9, 8]}, {'name': 'Mike', 'seq': [11, 2]}]
In my template I sorted them with:
{{ data|dictsort:"name" }}
I'd like to have {'name': 'All names', 'seq': [9, 8]} in the top of the list and keep the other sorted data items. How can I do this?

Do the sorting in the view, using a custom key function.
data.sort(key=lambda d: '0' if d['name'] == 'All names' else d['name'])

Related

Django dynamic verbose name

I'm struggling to think about how to achieve this. What I want to do is have a series of questions (to represent a Likert table) in a CharField object like so:
for a in range(1, 11):
locals()['ATL' + str(a)] = models.PositiveIntegerField(
choices=[
[1, 'Disagree Completely'],
[2, 'Disagree Strongly'],
[3, 'Disagree'],
[4, 'Neutral'],
[5, 'Agree'],
[5, 'Agree Strongly'],
[7, 'Agree Completely'],
],
widget=widgets.RadioSelectHorizontal(),
verbose_name = Constants.ATL_qu_list[a-1])
del a
And then change the verbose name for the question depending on the question number (again, I know I'm not supposed to be using locals() to store variables). Is there an easier way of achieving a dynamic label though? Thanks!
Okay, here's my answer (as well as a clarification for what I am looking for). Basically I had a series of Likert questions to put to participants which I wanted to represent as CharFields. Because each Likert question uses the same seven choice scale, it seems like inefficient coding to repeat the same functionality and only change the verbose name between each declaration.
Accordingly, I've instead used this method to achieve what I want:
# Reads in the list of survey questions
with open('survey/survey_questions.csv') as csvfile:
data_read = list(csv.reader(csvfile))
...
for a in range(1, 11):
locals()['ATL' + str(a)] = models.PositiveIntegerField(
choices=[
[1, 'Disagree Completely'],
[2, 'Disagree Strongly'],
[3, 'Disagree'],
[4, 'Neutral'],
[5, 'Agree'],
[6, 'Agree Strongly'],
[7, 'Agree Completely'],
],
widget=widgets.RadioSelectHorizontal(),
verbose_name = data_read[a-1][0])
del a

Understanding *[] in python passed to .agg() in pyspark

I am trying to understand how the *[] allows me to pass parameters to this
aggregate in pyspark. This runs, but I am trying to reuse the code in another example and was hoping someone could point me to the appropriate documentation so that I knew what was going on here. I like that it can pass the columns in the list as a parameter.
I was hoping that either someone knew what *[] is doing here.
How does it know to append a column to the DataFrame and not just iterate through the list, and execute once for each element in testdata.
import pyspark.sql.functions as fn
spark = SparkSession.builder.getOrCreate()
testdata= spark.createDataFrame([
(1, 144.5, 5.9, 33, 'M'),
(2, 167.2, None, 45, 'M'),
(3, 124.1, 5.2, 23, 'F'),
(4, None, 5.9, None, 'M'),
(5, 133.2, 5.7, 54, 'F'),
(3, 124.1, None, None, 'F'),
(5, 129.2, 5.3, None, 'M'),
],
['id', 'weight', 'height', 'age', 'gender']
)
testdata.where(
fn.col("gender") == 'M'
).select(
'*'
).agg(*[
(1 - (fn.count(c) / fn.count('*'))).alias(c + '_missing')
for c in testdata.columns
]).toPandas()
output:
+----------+--------------+--------------+-----------+--------------+
|id_missing|weight_missing|height_missing|age_missing|gender_missing|
+----------+--------------+--------------+-----------+--------------+
| 0.0| 0.25| 0.25| 0.5| 0.0|
+----------+--------------+--------------+-----------+--------------+
Using * in front of a list expands out the members as individual arguments. So, the following two function calls will be equivalent:
my_function(*[1, 2, 3])
my_function(1, 2, 3)
Obviously, the first one is not very useful if you already know the precise number of arguments. It becomes more useful with a comprehension like you are using, where is is not clear how many items will be in the list.

Getting results of dropdown lists

im a beginner in using Django. I need to create a Game for my University project.
I have some different questions, which have always 4 different answers. The answers will once have different values for the player, but im not that far, yet.
I did this in a dropdown list:
class Player(BasePlayer):
Antwort1 = models.IntegerField(
choices=[
[1, 'Mitfahrgelegenheit'],
[2, 'BlaBlaCar'],
[3, 'FlixBus'],
[4, 'Mitfahrzentrale'],
[5, ' ']
], default=5)
Antwort2 = models.IntegerField(
choices=[
[1, 'Mitfahrgelegenheit'],
[2, 'BlaBlaCar'],
[3, 'FlixBus'],
[4, 'Mitfahrzentrale'],
[5, ' ']
], default=5)
Antwort3 = models.IntegerField(
choices=[
[1, 'Mitfahrgelegenheit'],
[2, 'BlaBlaCar'],
[3, 'FlixBus'],
[4, 'Mitfahrzentrale'],
[5, ' ']
], default=5)
and so on...
How can I get the results out of the choices?
If I put {{% form.answer1 %}} in my result page, the result in fact is the answer, but shown as a drop down list.
thanks for your help and best whises,
Julian

Python: insert new element into sorted list of dictionaries

I've got a list of dictionaries that is already sorted by a key id.
y = [{'id': 0, 'name': 'Frank'},
{'id': 5, 'name': 'Hank'},
{'id': 8, 'name': 'Fred'},
{'id': 30, 'name': 'Jill'}]
I want to insert a new element into the list.
y.append({'id': 6, 'name': 'Jenkins'})
How do I avoid sorting the list again as follows once the new element is added?
y = sorted(y, key=lambda x: x['id'])
The ideal outcome is:
y = [{'id': 0, 'name': 'Frank'},
{'id': 5, 'name': 'Hank'},
{'id': 6, 'name': 'Jenkins'},
{'id': 8, 'name': 'Fred'},
{'id': 30, 'name': 'Jill'}]
Edit:
Using bisect.insort(y, {'id': 6, 'name': 'Jenkins'}) will work only for the first key, if the dict is sorted by name, it will fail.
Since a insertion in a list is in O(n) anyway, any clever bisect algorithm is not that useful, so you can simply loop the list to find the position where it should be inserted, and then insert it. Something like:
new_value = {'id': 6, 'name': 'Jenkins'}
for index, value in enumerate(y):
# Assuming y is in increasing order.
if value['id'] > new_value['id']:
y.insert(index, new_value)
break
I recommend to change your dict to a class, overload the comparison operator, and then use bisect.insort(). I don't recommend to iterate over all items to find the insert location as proposed in the other reply. From theory, the complexity is still O(n), but, but searching the item takes much longer than inserting a new element. I guess inserting will just do a few memcopies, while for the search you have to compare every single element.
From my example, iterating to find the location, then insert takes about 2 minutes to complete. The same data with bisect.insert() takes about 10 seconds.

Get specific value by key from nested dictionaries/lists

I am trying to return "blue" only (ignore other colors) from color_menu in this list/dict:
{'id': 10, 'color_menu': [{'color': 'blue', 'name': 'Sandra'}, {'color': 'red', 'name': 'Lisa'}]}
I am able to return all three colors but haven't been able to isolate and return just blue.
Just chain the indexes:
>>> x = {'id': 10, 'color_menu': [{'color': 'blue', 'name': 'Sandra'}, {'color': 'red', 'name': 'Lisa'}]}
>>> x["color_menu"][0]["color"]
'blue'
Note that this is kinda unreadable: only do it this way if you can't reshape the data structures in any way.
Explanation:
dictionaries are unordered and are indexed (usually) by key, though it's possible to index by value. in this case, the keys are strings and the values are more objects.
lists are indexed by their numeric index.
dictionaries inside lists inside dictionaries (known as "nested") are no different: the syntax is sensical.