I am trying to order the results downloaded from Firestore.
I download and print the result and they are out of order, after ordering them I bring them again and they print in order of date, but the result in the recycler view doesn't update.
This is the code I use to order the list, originally it is an array list of hash map but I convert it to a mutable list so I can order it and then back to an array list.
val newList = messagesInfo.sortedWith(compareBy {
it.dateC }).toMutableList()
messagesInfo = newList as ArrayList<MessagesPost>
println("Tony the date new list array is $messagesInfo")
messagesAdapter.notifyDataSetChanged()
I have figured this out.
by moving my submit list down under the reassignment of the array.
val newList = messagesInfo.sortedWith(compareBy {
it.dateC }).toMutableList().reversed()
messagesInfo = newList as ArrayList<MessagesPost>
messagesAdapter.submitList(messagesInfo)
messagesAdapter.notifyDataSetChanged()
Related
I want to sort a list of strings (with possibly duplicate entries) by using as ordering reference the order of the entries in another list. So, the following list is the list I want to sort
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
And the list that specifies the order is
List<String> order = ['orange','apple','x','pear'];
And the output should be
List<String> result = ['orange','apple','apple','x','x','x','pear','pear'];
Is there a clean way of doing this?
I don't understand if I can use list's sort and compare with the following problem. I tried using map, iterable, intersection, etc.
There might be a more efficient way but at least you get the desired result:
main() {
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
List<String> order = ['orange','apple','x','pear'];
list.sort((a, b) => order.indexOf(a).compareTo(order.indexOf(b)));
print(list);
}
Try it on DartPad
The closure passed to list.sort(...) is a custom comparer which instead of comparing the passed item, compares their position in order and returns the result.
Using a map for better lookup performance:
main() {
List<String> list = ['apple','pear','apple','x','x','orange','x','pear'];
List<String> orderList = ['orange','apple','x','pear'];
Map<String,int> order = new Map.fromIterable(
orderList, key: (key) => key, value: (key) => orderList.indexOf(key));
list.sort((a, b) => order[a].compareTo(order[b]));
print(list);
}
Try it on DartPad
Lets say I have a table like so:
{
value = 4
},
{
value = 3
},
{
value = 1
},
{
value = 2
}
and I want to iterate over this and print the value in order so the output is like so:
1
2
3
4
How do I do this, I understand how to use ipairs and pairs, and table.sort, but that only works if using table.insert and the key is valid, I need to be loop over this in order of the value.
I tried a custom function but it simply printed them in the incorrect order.
I have tried:
Creating an index and looping that
Sorting the table (throws error: attempt to perform __lt on table and table)
And a combination of sorts, indexes and other tables that not only didn't work, but also made it very complicated.
I am well and truly stumped.
Sorting the table
This was the right solution.
(throws error: attempt to perform __lt on table and table)
Sounds like you tried to use a < b.
For Lua to be able to sort values, it has to know how to compare them. It knows how to compare numbers and strings, but by default it has idea how to compare two tables. Consider this:
local people = {
{ name = 'fred', age = 43 },
{ name = 'ted', age = 31 },
{ name = 'ned', age = 12 },
}
If I call sort on people, how can Lua know what I intend? I doesn't know what 'age' or 'name' means or which I'd want to use for comparison. I have to tell it.
It's possible to add a metatable to a table which tells Lua what the < operator means for a table, but you can also supply sort with a callback function that tells it how to compare two objects.
You supply sort with a function that receives two values and you return whether the first is "less than" the second, using your knowledge of the tables. In the case of your tables:
table.sort(t, function(a,b) return a.value < b.value end)
for i,entry in ipairs(t) do
print(i,entry.value)
end
If you want to leave the original table unchanged, you could create a custom 'sort by value' iterator like this:
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
-- build new table to sort
local sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
-- sort new table
table.sort( sorted, valueSort );
-- return iterator
return ipairs( sorted );
end
When sortByValue() is called, it clones tbl to a new sorted table, and then sorts the sorted table. It then hands the sorted table over to ipairs(), and ipairs outputs the iterator to be used by the for loop.
To use:
for i,v in sortByValue( myTable ) do
print(v)
end
While this ensures your original table remains unaltered, it has the downside that each time you do an iteration the iterator has to clone myTable to make a new sorted table, and then table.sort that sorted table.
If performance is vital, you can greatly speed things up by 'caching' the work done by the sortByValue() iterator. Updated code:
local resort, sorted = true;
local function valueSort(a,b)
return a.value < b.value;
end
function sortByValue( tbl ) -- use as iterator
if not sorted then -- rebuild sorted table
sorted = {};
for i,v in ipairs( tbl ) do sorted[i] = v end;
resort = true;
end
if resort then -- sort the 'sorted' table
table.sort( sorted, valueSort );
resort = false;
end
-- return iterator
return ipairs( sorted );
end
Each time you add or remove an element to/from myTable set sorted = nil. This lets the iterator know it needs to rebuild the sorted table (and also re-sort it).
Each time you update a value property within one of the nested tables, set resort = true. This lets the iterator know it has to do a table.sort.
Now, when you use the iterator, it will try and re-use the previous sorted results from the cached sorted table.
If it can't find the sorted table (eg. on first use of the iterator, or because you set sorted = nil to force a rebuild) it will rebuild it. If it sees it needs to resort (eg. on first use, or if the sorted table was rebuilt, or if you set resort = true) then it will resort the sorted table.
I have a class
#Sortable(includes = ['date'])
class Item {
// other fields not relevant to this question
Date date
}
If I sort a List of these objects it will sort them in ascending order based on the date field. Is there a way to sort them in descending order instead? I know I could just call reverse() on the result of the ascending sort, but this seems a bit inefficient
Here are a couple of ways:
def items = [
new Item(date: new Date(40000)),
new Item(date: new Date(1000)),
new Item(date: new Date(200000)),
new Item(date: new Date(00100)),
]
items.sort { a, b -> b <=> a }
items.sort(true, Collections.reverseOrder())
I have an Action method in my controller which returns a List Object
Public ActionResult GetCats(long Id,string strsortorder,string dltIds)
{
var Result=objrepo.GetCats(Id);//this method returns me List of Result
}
My array looks like this:
var Result=[{CatId:1015,CatName:Abc},{CatId:1016,CatName:Acd},
{CatId:1017,CatName:Adf},{CatId:1018,CatName:CDdf},{CatId:1019,CatName:asdas},
{CatId:1020,CatName:Abc},{CatId:1021,CatName:Abc},{CatId:1022,CatName:Abc},
{CatId:1023,CatName:Abc},{CatId:1024,CatName:Abc}]
What I want to do is:
Using two more parameters in my Action Method "strsortorder" and "dltIds"
that have a list of ids like this:
strsortorder="1021,1015,1016,1019,1022";
dltIds="1017,1018,1020";
From this the "Result" returned from my method , I want to remove the records which are in "dltids" and the remaining array should be sorted in the order which I have in "strsortorder";
In the end the new object should look like this:
var NewResult=[{CatId:1021,CatName:Abc},{CatId:1015,CatName:Abc},
{CatId:1016,CatName:Acd},{CatId:1019,CatName:asdas},{CatId:1022,CatName:Abc},
{CatId:1023,CatName:Abc},{CatId:1024,CatName:Abc}]
Can any one help me in acheiving this in linq or any other way?
I want to avoid any type of loop or froeach here for max extent, I know it can be done by looping but I want to avoid this since the result can sometimes contain large amounts of data.
I realized you can use an ArrayList instead of a Dictionary and it would be faster. I think Dictionary is clear how it works but here is the "better" implementation using array list:
var excludeList = dltIds.Split(",".ToCharArray());
ArrayList sortList = new ArrayList(strsortorder.Split(",".ToCharArray()));
var NewResult =
Result.Where(item => ! excludeList.Contains(item.CatId.ToString()))
.OrderBy(item => {
if (sortList.Contains(item.CatId.ToString()))
return sortList.IndexOf(item.CatId.ToString());
return sortList.Count;
});
Original answer below:
Public ActionResult GetCats(long Id,string strsortorder,string dltIds)
{
var Result=objrepo.GetCats(Id);//this method returns me List of Result
var excludeList = dltIds.Split(",".ToCharArray());
int orderCount = 0; // used in the closure creating the Dictionary below
var sortList = strsortorder.Split(",".ToCharArray())
.ToDictionary(x => x,x => orderCount++);
// filter
var NewResult =
Result.Where(item => ! excludeList.Contains(item.CatId.ToString()))
.OrderBy(item => {
if (sortList.ContainsKey(item.CatId.ToString()))
return sortList[item.CatId.ToString()];
return sortList.Count();
});
}
How this works:
First I create lists out of your comma separated exclude list using split.
This I create a dictionary with the key being the ordering ID and the value being an integer that goes up by one.
For the filtering I look to see if an item is in the exclude array before I continue processing the item.
I then do a sort on matching against the key and the dictionary and returning the value -- this will sort things in the order of the list since I incremented a counter when creating the values. If an item is not in the dictionary I return one more than the maximum value in the dictionary which must be the count of the items. (I could have used the current value of orderCount instead.)
Questions?
I have a program with multiple int variables where individual counts are added to the specific variable each time a set fail condition is encountered. I want the user to be able to track how many failures of each category they have encountered by a button click. I want to display the range on a datagridview in order from highest value integer down to lowest. I also need to display in the adjacent column the name of the test step that relates to the value. My plan was to use Array.sort to order the integers but i then lose track of their names so cant assign the adjacent string column. I tried using a hashtable but if i use the string as a key it sorts alphabetically not numerically and if i use the integer as a key i get duplicate entries which dont get added to the hash table. here is some of the examples i tried but they have the aforementioned problems. essentially i want to end with two arrays where the order matches the naming and value convention. FYI the variables were declared before this section of code, variables ending in x are the string name for the (non x) value of the integer.
Hashtable sorter = new Hashtable();
sorter[download] = downloadx;
sorter[power] = powerx;
sorter[phase] = phasex;
sorter[eeprom] = eepromx;
sorter[upulse] = upulsex;
sorter[vpulse] = vpulsex;
sorter[wpulse] = wpulsex;
sorter[volts] = voltsx;
sorter[current] = currentx;
sorter[ad] = adx;
sorter[comms] = commsx;
sorter[ntc] = ntcx;
sorter[prt] = prtx;
string list = "";
string[] names = new string[13];
foreach (DictionaryEntry child in sorter)
{
list += child.Value.ToString() + "z";
}
int[] ordered = new int[] { download, power, phase, eeprom, upulse, vpulse, wpulse, volts, current, ad, comms, ntc, prt };
Array.Sort(ordered);
Array.Reverse(ordered);
for (int i = 0; i < sorter.Count; i++)
{
int pos = list.IndexOf("z");
names[i] = list.Substring(0, pos);
list = list.Substring(pos + 1);
}
First question here so hope its not too longwinded.
Thanks
Use a Dictionary. And you can order it by the value : myDico.OrderBy(x => x.Value).Reverse(), the sort will be numerical descending. You just have to enumerate the result.
I hope I understand your need. Otherwise ignore me.
You want to be using a
Dictionary <string, int>
to store your numbers.I'm not clear on how you're displaying results at the end - do you have a grid or a list control?
You ask about usings. Which ones do you already have?
EDIT for .NET 2.0
There might be a more elegant solution, but you could implement the logic by putting your rows in a DataTable. Then you can make a DataView of that table and sort by whichever column you like, ascending or descending.
See http://msdn.microsoft.com/en-us/library/system.data.dataview(v=VS.80).aspx for example.
EDIT for .NET 3.5 and higher
As far as sorting a Dictionary by its values:
var sortedEntries = myDictionary.OrderBy(pair => pair.Value);
If you need the results to be a Dictionary, you can call .ToDictionary() on that. For reverse order, use .OrderByDescending(pair => pair.Value).