Iterating through multiple lists in Django templates - django

views.py
def exa(request):
list1 = ["apple", "banana", "cherry"]
list2 = [1, 5, 7]
list3 = [True, False, False]
context = {
'l1' : list1,
'l2' : list2,
'l3' : list3,
}
return render(request, 'patient_registration/111.html', context)
template
{%for a, b in zip(l1, l2)%}
{{a}}
{{b}}
{%endfor%}
template can be not show any list
i want to display multipe list thorugh context in template

You can use zip in your view:
mylist = zip(list1, list2, list3)
context = {
'mylist': mylist
}
and in your template use:
{% for item1, item2, item3 in mylist %}
to iterate through your lists.

Related

Django only returns last row of dict in template

I am trying to return the values from a Dict in Django.
My views.py prints the the correct data in the terminal when doing a GET-request to my page, however, in my template I only get the last line of the dictionary.
I have tried looping the dict in my template and all sorts of combinations but I can't seem to make it work. Am I missing something? For instance, in the template below I print the entire dict. But it still only prints the last row somehow.
views.py
fruits = [
'Apple', 'Banana', 'Orange']
for fruit in fruits:
price_change = historical_prices['price_change'][::-1]
low_price = 0
for day in price_change:
if day < -0.1:
low_price += 1
else:
break
if low_price >= 0:
ls_dict = {'fruit': fruit, 'low_price': low_price}
print(ls_dict)
return render(request, "prices/index.html", {
"ls_dict": ls_dict,
})
Template
<p>{{ ls_dict }}</p>
Template output
{'fruit': 'Orange', 'low_price': 1}
Correct print which views.py produces
{'fruit': 'Apple', 'low_price': 1}
{'fruit': 'Banana', 'low_price': 3}
{'fruit': 'Orange', 'low_price': 1}
The print() seems correct, but you are just overriding the variable over and over again, thus ls_dict will only be the set with the last iteration of the for loop.
You can test this by print(ls_dict) outside of the for-loop
Try the following:
ls_list = []
for fruit in fruits:
price_change = historical_prices['price_change'][::-1]
low_price = 0
for day in price_change:
if day < -0.1:
low_price += 1
else:
break
if low_price >= 0:
ls_dict = {'fruit': fruit, 'low_price': low_price}
ls_list.append(ls_dict)
return render(request, "prices/index.html", {
"ls_list": ls_list,
})

how to add data to list of dictionaries in Django

I want to add data to list of dictionaries
a =[100, 200, 300]
b =['apple', 'orange', 'grapes']
c=[]
for val in a:
c.append({'price':val})
for val in b:
c.append({'fruit':val})
print(c)
result should be like this:
[
{'price':100, 'fruit':'apple'}, {'price':200, 'fruit':'orange'}, {'price':300, 'fruit':'grapes'}
You can work with list comprehension:
a = [100, 200, 300]
b = ['apple', 'orange', 'grapes']
c = [{'price': p, 'fruit': f} for p, f in zip(a, b)]

making sublists from a list and adding all sublists in one list in Flutter

Can anybody help me with list concepts?
I have a List of names and I want to make sublists of words with the same letter then add all those sublists in a list.
this is my code:
List<String> items = [
'one',
'two',
'three',
'four',
'five',
'six',
'seven',
'eight',
'nine',
'ten'
];
List<String> sublist;
#override
void initState() {
super.initState();
//----- sort alphabetically
items.sort((a, b) =>
a.toString().toLowerCase().compareTo(b.toString().toLowerCase()));
//----- get the initials
sublist = items.map((element) => element[0]).toList();
//----- remove duplicates
sublist = sublist.toSet().toList();
// ---------------- generate lists
List s = [];
List<List> listOfLists = [];
sublist.forEach((letter) async {
items.forEach((item) =>
item.startsWith(letter) ? s.add(item) : {items.iterator.moveNext()});
listOfLists.add(s);
print(letter);
print(s);
s.clear();
});
print(listOfLists);
this is what I want to get from listOfList : [ [eight], [five, four], [nine], [one], [seven, six], [ten, three, two] ]
but I just get empty sublists:
Here is my result: enter image description here
You are clearing the lists in each iteration.
Remove s.clear() and move List s = [] inside the for each function
// ---------------- generate lists
List<List> listOfLists = [];
sublist.forEach((letter) async {
List s = [];
items.forEach((item) => item.startsWith(letter) ? s.add(item) : {items.iterator.moveNext()});
listOfLists.add(s);
print(letter);
print(s);
});
Anyway, I would recommend you not to use forEach inside another forEach
You can then use:
List<List> listOfLists = [];
sublist.forEach((letter) async {
List s = items.where((item) => item.startsWith(letter)).toList();
listOfLists.add(s);
});

How can I delete duplicates in a Dart List? list.distinct()?

How do I delete duplicates from a list without fooling around with a set? Is there something like list.distinct()? or list.unique()?
void main() {
print("Hello, World!");
List<String> list = ['abc',"abc",'def'];
list.forEach((f) => print("this is list $f"));
Set<String> set = new Set<String>.from(list);
print("this is #0 ${list[0]}");
set.forEach((f) => print("set: $f"));
List<String> l2= new List<String>.from(set);
l2.forEach((f) => print("This is new $f"));
}
Hello, World!
this is list abc
this is list abc
this is list def
this is #0 abc
set: abc
set: def
This is new abc
This is new def
Set seems to be way faster!! But it loses the order of the items :/
Use toSet and then toList
var ids = [1, 4, 4, 4, 5, 6, 6];
var distinctIds = ids.toSet().toList();
Result: [1, 4, 5, 6]
Or with spread operators:
var distinctIds = [...{...ids}];
I didn't find any of the provided answers very helpful.
Here is what I generally do:
final ids = Set();
myList.retainWhere((x) => ids.add(x.id));
Of course you can use any attribute which uniquely identifies your objects. It doesn't have to be an id field.
Benefits over other approaches:
Preserves the original order of the list
Works for rich objects not just primitives/hashable types
Doesn't have to copy the entire list to a set and back to a list
Update 09/12/21
You can also declare an extension method once for lists:
extension Unique<E, Id> on List<E> {
List<E> unique([Id Function(E element)? id, bool inplace = true]) {
final ids = Set();
var list = inplace ? this : List<E>.from(this);
list.retainWhere((x) => ids.add(id != null ? id(x) : x as Id));
return list;
}
}
This extension method does the same as my original answer. Usage:
// Use a lambda to map an object to its unique identifier.
myRichObjectList.unique((x) => x.id);
// Don't use a lambda for primitive/hashable types.
hashableValueList.unique();
Set works okay, but it doesn't preserve the order. Here's another way using LinkedHashSet:
import "dart:collection";
void main() {
List<String> arr = ["a", "a", "b", "c", "b", "d"];
List<String> result = LinkedHashSet<String>.from(arr).toList();
print(result); // => ["a", "b", "c", "d"]
}
https://api.dart.dev/stable/2.4.0/dart-collection/LinkedHashSet/LinkedHashSet.from.html
Try the following:
List<String> duplicates = ["a", "c", "a"];
duplicates = duplicates.toSet().toList();
Check this code on Dartpad.
If you want to keep ordering or are dealing with more complex objects than primitive types, store seen ids to the Set and filter away those ones that are already in the set.
final list = ['a', 'a', 'b'];
final seen = Set<String>();
final unique = list.where((str) => seen.add(str)).toList();
print(unique); // => ['a', 'b']
//This easy way works fine
List<String> myArray = [];
myArray = ['x', 'w', 'x', 'y', 'o', 'x', 'y', 'y', 'r', 'a'];
myArray = myArray.toSet().toList();
print(myArray);
// result => myArray =['x','w','y','o','r', 'a']
I am adding this to atreeon's answer. For anyone that want use this with Object:
class MyObject{
int id;
MyObject(this.id);
#override
bool operator ==(Object other) {
return other != null && other is MyObject && hashCode == other.hashCode;
}
#override
int get hashCode => id;
}
main(){
List<MyObject> list = [MyObject(1),MyObject(2),MyObject(1)];
// The new list will be [MyObject(1),MyObject(2)]
List<MyObject> newList = list.toSet().toList();
}
Remove duplicates from a list of objects:
class Stock {
String? documentID; //key
Make? make;
Model? model;
String? year;
Stock({
this.documentID,
this.make,
this.model,
this.year,
});
}
List of stock, from where we want to remove duplicate stocks
List<Stock> stockList = [stock1, stock2, stock3];
Remove duplicates
final ids = stockList.map((e) => e.documentID).toSet();
stockList.retainWhere((x) => ids.remove(x.documentID));
Using Dart 2.3+, you can use the spread operators to do this:
final ids = [1, 4, 4, 4, 5, 6, 6];
final distinctIds = [...{...ids}];
Whether this is more or less readable than ids.toSet().toList() I'll let the reader decide :)
For distinct list of objects you can use Equatable package.
Example:
// ignore: must_be_immutable
class User extends Equatable {
int id;
String name;
User({this.id, this.name});
#override
List<Object> get props => [id];
}
List<User> items = [
User(
id: 1,
name: "Omid",
),
User(
id: 2,
name: "Raha",
),
User(
id: 1,
name: "Omid",
),
User(
id: 2,
name: "Raha",
),
];
print(items.toSet().toList());
Output:
[User(1), User(2)]
Here it is, a working solution:
var sampleList = ['1', '2', '3', '3', '4', '4'];
//print('original: $sampleList');
sampleList = Set.of(sampleList).toList();
//print('processed: $sampleList');
Output:
original: [1, 2, 3, 3, 4, 4]
processed: [1, 2, 3, 4]
Using the fast_immutable_collections package:
[1, 2, 3, 2].distinct();
Or
[1, 2, 3, 2].removeDuplicates().toList();
Note: While distinct() returns a new list, removeDuplicates() does it lazily by returning an Iterable. This means it is much more efficient when you are doing some extra processing. For example, suppose you have a list with a million items, and you want to remove duplicates and get the first five:
// This will process five items:
List<String> newList = list.removeDuplicates().take(5).toList();
// This will process a million items:
List<String> newList = list.distinct().sublist(0, 5);
// This will also process a million items:
List<String> newList = [...{...list}].sublist(0, 5);
Both methods also accept a by parameter. For example:
// Returns ["a", "yk", "xyz"]
["a", "yk", "xyz", "b", "xm"].removeDuplicates(by: (item) => item.length);
If you don't want to include a package into your project but needs the lazy code, here it is a simplified removeDuplicates():
Iterable<T> removeDuplicates<T>(Iterable<T> iterable) sync* {
Set<T> items = {};
for (T item in iterable) {
if (!items.contains(item)) yield item;
items.add(item);
}
}
Note: I am one of the authors of the fast_immutable_collections package.
void uniqifyList(List<Dynamic> list) {
for (int i = 0; i < list.length; i++) {
Dynamic o = list[i];
int index;
// Remove duplicates
do {
index = list.indexOf(o, i+1);
if (index != -1) {
list.removeRange(index, 1);
}
} while (index != -1);
}
}
void main() {
List<String> list = ['abc', "abc", 'def'];
print('$list');
uniqifyList(list);
print('$list');
}
Gives output:
[abc, abc, def]
[abc, def]
As for me, one of the best practices is sort the array, and then deduplicate it. The idea is stolen from low-level languages. So, first make the sort by your own, and then deduplicate equal values that are going after each other.
// Easy example
void dedup<T>(List<T> list, {removeLast: true}) {
int shift = removeLast ? 1 : 0;
T compareItem;
for (int i = list.length - 1; i >= 0; i--) {
if (compareItem == (compareItem = list[i])) {
list.removeAt(i + shift);
}
}
}
// Harder example
void dedupBy<T, I>(List<T> list, I Function(T) compare, {removeLast: true}) {
int shift = removeLast ? 1 : 0;
I compareItem;
for (int i = list.length - 1; i >= 0; i--) {
if (compareItem == (compareItem = compare(list[i]))) {
list.removeAt(i + shift);
}
}
}
void main() {
List<List<int>> list = [[1], [1], [2, 1], [2, 2]];
print('$list');
dedupBy(list, (innerList) => innerList[0]);
print('$list');
print('\n removeLast: false');
List<List<int>> list2 = [[1], [1], [2, 1], [2, 2]];
print('$list2');
dedupBy(list2, (innerList) => innerList[0], removeLast: false);
print('$list2');
}
Output:
[[1], [1], [2, 1], [2, 2]]
[[1], [2, 1]]
removeLast: false
[[1], [1], [2, 1], [2, 2]]
[[1], [2, 2]]
This is another way...
final reducedList = [];
list.reduce((value, element) {
if (value != element)
reducedList.add(value);
return element;
});
reducedList.add(list.last);
print(reducedList);
It works for me.
var list = [
{"id": 1, "name": "Joshua"},
{"id": 2, "name": "Joshua"},
{"id": 3, "name": "Shinta"},
{"id": 4, "name": "Shinta"},
{"id": 5, "name": "Zaidan"}
];
list.removeWhere((element) => element.name == element.name.codeUnitAt(1));
list.sort((a, b) => a.name.compareTo(b.name));
Output:
[{"id": 1, "name": "Joshua"},
{"id": 3, "name": "Shinta"},
{"id": 5, "name": "Zaidan"}]
List<Model> bigList = [];
List<ModelNew> newList = [];
for (var element in bigList) {
var list = newList.where((i) => i.type == element.type).toList();
if(list.isEmpty){
newList.add(element);
}
}
Create method to remove duplicates from Array and return Array of unique elements.
class Utilities {
static List<String> uniqueArray(List<String> arr) {
List<String> newArr = [];
for (var obj in arr) {
if (newArr.contains(obj)) {
continue;
}
newArr.add(obj);
}
return newArr;
}
}
You can use the following way:
void main(List <String> args){
List<int> nums = [1, 2, 2, 2, 3, 4, 5, 5];
List<int> nums2 = nums.toSet().toList();
}
NOTE: This will not work if the items in the list are objects of class and have the same attributes. So, to solve this, you can use the following way:
void main() {
List<Medicine> objets = [Medicine("Paracetamol"),Medicine("Paracetamol"), Medicine("Benylin")];
List <String> atributs = [];
objets.forEach((element){
atributs.add(element.name);
});
List<String> noDuplicates = atributs.toSet().toList();
print(noDuplicates);
}
class Medicine{
final String name;
Medicine(this.name);
}
This is my solution
List<T> removeDuplicates<T>(List<T> list, IsEqual isEqual) {
List<T> output = [];
for(var i = 0; i < list.length; i++) {
bool found = false;
for(var j = 0; j < output.length; j++) {
if (isEqual(list[i], output[j])) {
found = true;
}
}
if (found) {
output.add(list[i]);
}
}
return output;
}
Use it like this:
var theList = removeDuplicates(myOriginalList, (item1, item2) => item1.documentID == item2.documentID);
or...
var theList = removeDuplicates(myOriginalList, (item1, item2) => item1.equals(item2));
or...
I have a library called Reactive-Dart that contains many composable operators for terminating and non-terminating sequences. For your scenario it would look something like this:
final newList = [];
Observable
.fromList(['abc', 'abc', 'def'])
.distinct()
.observe((next) => newList.add(next), () => print(newList));
Yielding:
[abc, def]
I should add that there are other libraries out there with similar features. Check around on GitHub and I'm sure you'll find something suitable.

Howto add properties to the output of unordered_list?

I am using an unordered_list tag in django.
I have the following list:
foo = ['A', ['B', 'C', 'D'], 'E']
And the following tag:
{{ foo|unordered_list }}
Which produces, as expected the following:
<li>A
<ul>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
</li>
<li>E</li>
What I would like to do is to add id and class properties to each "li" node.
I understand that I can do it in JavaScript, or implement my own template tag in django. But I wanted to ask first. May be there already exists an easy build-in way to do it in django template?
As you can see in the source, the <li> is hardcoded so you can't do it without creating your own templatefilter.
def unordered_list(value, autoescape=None):
"""
Recursively takes a self-nested list and returns an HTML unordered list --
WITHOUT opening and closing <ul> tags.
The list is assumed to be in the proper format. For example, if ``var``
contains: ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``,
then ``{{ var|unordered_list }}`` would return::
<li>States
<ul>
<li>Kansas
<ul>
<li>Lawrence</li>
<li>Topeka</li>
</ul>
</li>
<li>Illinois</li>
</ul>
</li>
"""
if autoescape:
from django.utils.html import conditional_escape
escaper = conditional_escape
else:
escaper = lambda x: x
def convert_old_style_list(list_):
"""
Converts old style lists to the new easier to understand format.
The old list format looked like:
['Item 1', [['Item 1.1', []], ['Item 1.2', []]]
And it is converted to:
['Item 1', ['Item 1.1', 'Item 1.2]]
"""
if not isinstance(list_, (tuple, list)) or len(list_) != 2:
return list_, False
first_item, second_item = list_
if second_item == []:
return [first_item], True
old_style_list = True
new_second_item = []
for sublist in second_item:
item, old_style_list = convert_old_style_list(sublist)
if not old_style_list:
break
new_second_item.extend(item)
if old_style_list:
second_item = new_second_item
return [first_item, second_item], old_style_list
def _helper(list_, tabs=1):
indent = u'\t' * tabs
output = []
list_length = len(list_)
i = 0
while i < list_length:
title = list_[i]
sublist = ''
sublist_item = None
if isinstance(title, (list, tuple)):
sublist_item = title
title = ''
elif i < list_length - 1:
next_item = list_[i+1]
if next_item and isinstance(next_item, (list, tuple)):
# The next item is a sub-list.
sublist_item = next_item
# We've processed the next item now too.
i += 1
if sublist_item:
sublist = _helper(sublist_item, tabs+1)
sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist,
indent, indent)
output.append('%s<li>%s%s</li>' % (indent,
escaper(force_unicode(title)), sublist))
i += 1
return '\n'.join(output)
value, converted = convert_old_style_list(value)
return mark_safe(_helper(value))
unordered_list.is_safe = True
unordered_list.needs_autoescape = True
It should be fairly easy to rewrite the filter to add id/class support though, depending on how you want it to work.