Sorting and grouping in kotlin - sorting

I have a list of objects in the kotlin and I want to sort them by number and then by string. Is there a way to do this? I've gone through hundreds of articles, but nothing works anywhere.
myList.sortedWith(compareBy<Item> {it.name.id }.thenBy{it.name.secondname})
This code do not works.
Of course myList is a type of Item.
Greetings
#EDIT
But what if I have 10 same ids? The code will not reach the .thenBy check. Is there a possibility to check a whole pair of fields?

myList.sortedWith(compareBy<Item> {it.name.id }.thenBy{it.name.secondname}) returns a sorted copy of the list, but it doesn't modify the original one.
If you want the original list to be modified, you can either use sortWith instead of sortedWith:
myList.sortWith(compareBy<Item> { it.name.id }.thenBy { it.name.secondname })
Or reassign myList variable:
myList = myList.sortedWith(compareBy<Item> { it.name.id }.thenBy { it.name.secondname })

Related

Is it possible to work with more than one array in vuetify v-autocomplete?

Normally one would just make a simple join to merge both arrays in one array, the problem is that i have arrays with different object structures, and depending on the type of object, i need to pass a different value.
Example:
array 1: fruits.type.name
array 2: animals.family.name
Is there any possibility other than having to craft a custom component from scratch using something like v-text-input, for example?
You mean something like this? Check this codesanbox I made:
https://codesandbox.io/s/stack-71429578-switch-autocomplete-array-757lve?file=/src/components/Example.vue
computed: {
autoArray() {
return this.typeAnimal ? this.animals : this.fruits
},
autoTypeId() {
return this.typeAnimal ? 'family.id' : 'type.id'
},
autoText() {
return this.typeAnimal ? 'family.name' : 'type.name'
}
}
With help of a couple computed props you could be able to switch array, item-text and item-value depending of the array you're working with.
As far as I know, there's no easy way to supply two different arrays to v-autocomplete and retain the search functionality.
You could probably join the arrays and write a custom filter property. Then use selection and item slots to change the output of the select based on the structure.
But if your data arrays aren't too complicated, I would avoid the above. Instead, I would loop through both arrays, and build a new combined one with a coherent structure.

Algorithm for visiting nodes only once

Let's say I have an array of N elements. I call a recursive function somehow like this: (no specific language here, just pseudocode)
recursive(myArray){
// do something awesome and provide base case etc
// also get mySecondArray based on myArray
for(i=0;i<mySecondArray.length;i++){
recursive(mySecondArray[i];
}
}
As you can see I need to call this function on every element of another array created inside based on some conditions and other functions called on myArray.
The problem I am having is that mySecondArray always has some of the elements that were already in myArray. I do not want to call recursion again on those elements.
Q: What would be the best algorithm approach to solve this?
If you need more info just let me know (I didn't get into details since it gets more complicated)
Thanks
You can have a hashmap/set/dictionary/whatever-you-call-it to look up the elements.
Python solution:
def recursive(myArray, mySet = None):
if mySet is None:
mySet = { myArray }
else:
mySet.add(myArray)
for mySecondArray in myArray:
if mySecondArray not in mySet:
recursive(myArray, mySet)
By the way writing recursive functions like that is a very bad idea in general. You should use a single function and a stack of the arguments if possible.
P.S.: Your code was incomplete by the way but the idea is the same.

Order $each by name

I am trying to figure why my ajax $each alters the way my list of names gets printed?
I have an json string like this:
[{"name":"Adam","len":1,"cid":2},{"name":"Bo","len":1,"cid":1},{"name":"Bob","len":1,"cid":3},{"name":"Chris","len":1,"cid":7},{"name":"James","len":1,"cid":5},{"name":"Michael","len":1,"cid":6},{"name":"Nick","len":1,"cid":4},{"name":"OJ","len":1,"cid":8}]
Here all the names are sorted in alphabetic order, but when getting them out they are sorted by "cid"? Why, and how can I change this?
Here is my jQuery:
var names = {};
$.getJSON('http://mypage.com/json/names.php', function(data){
$.each(data.courses, function (k, vali) {
names[vali.cid] = vali.name;
});
});
I guess its because "names[vali.cid]", but I need that part to stay that way. Can it still be done?
Hoping for help and thanks in advance :-.)
Ordering inside an object is not really defined or predictable when you iterate over it. I would suggest sorting the array based on an internal property:
var names = [];
$.getJSON('http://mypage.com/json/names.php', function(data){
$.each(data.courses, function (k, vali) {
names.push({name: vali.name, cid: vali.cid});
});
names.sort(function(a, b) {
return a.name.localeCompare(b.name);
});
});
Now you have an array that is ordered and you can iterate over it in a predictable order as well.
There is no "ajax $each" - you probably mean the jQuery function.
With "when getting them out" I presume you mean something like console.debug(names) after your $each call
Objects aren't ordered in javascript per definition, so there is no more order in your variable "names". Still, most javascript implementations today (and all the ones probably important to you - the ones used in the most used browsers) employ a stable order in objects which normally depends on the order you insert stuff.
All this said, there can probably be 3 reasons you're not getting what you're expecting:
Try console.debug(data) and see what you get - the order as you want it?
As you don't explicitly state how you debug your stuff, the problem could be in the way you output and not the data is stored. Here too try console.debug(names).
You're using a function which dereferences on expection, like console.*. This means if you console.debug() an object, the displayed values will depend on the moment you unfold the displayed tree in your browser, not when the line was called!

Grails mapping sort on multiple fields :: Groovy sort on multiple map entries

Stumped on this one. In Grails it seems one cannot define a default sort on multiple columns in domain mapping a la static mapping = { sort 'prop1 desc, prop2 asc' }, or { sort([prop1:'desc', prop2:'asc']) }. Only first column gets sorted, lame.
Similarly, when trying to Groovy sort a Grails findAllBy query on multiple columns, the second sort overrides the first.
def list = [[rowNum:2,position:3],[rowNum:1,position:2],[rowNum:3,position:1]]
list.sort{it.rowNum}.sort{it.position}
Obviously missing the boat on the latter case, the groovy sort. I have seen postings re: implementing comparable, but looking for something more concise if possible.
Here is a Groovy solution. Still essentially implementing a Comparator though.
list.sort { map1, map2 -> map1.rowNum <=> map2.rowNum ?: map1.position <=> map2.position }
Thanks to the link from GreenGiant, we see that the issue is closed as fixed as of version 2.3.
There is also example code:
static mapping =
{ sort([lastname:'asc', name:'asc']) }
It is working for me in 2.4.3
You can use String.format if you know max length. I assumed max 10 lenght:
list.sort { String.format('%010d%010d', it.rowNum, it.position) }

Linq intersect a child list of integers against a list of integers

I have a list of users each of which contains a list of associated storefront IDs. I have a separate list of integers and I want to find where any storefront id of a user matches any of the integers in the separate list.
I'm expecting something like this:
clientUsers = clientUsers.Where(x => x.Storefronts.Intersect(allowedStorefrontIds));
I'm told the type arguments can't be inferred from the usage on the Where extension method.
Do you know how I should structure my linq in this case?
You just need a .Any() in the lambda to check if the set-intersection contains any elements:
x => x.Storefronts.Intersect(allowedStorefrontIds).Any()
Personally, I would do something like this for efficiency:
var allowedIds = new HashSet<int>(allowedStorefrontIds);
var allowedUsers = clientUsers.Where(x => x.StoreFronts.Any(allowedIds.Contains));
Where expects a function that returns a boolean expression. Intersect returns a list. I think clientUsers.Intersect(allowedStorefrontIds) should return the list you're expecting, unless there is another list not mentioned in the code snippet.

Resources