2

I have a list of String as below:-

val a = listOf("G", "F", "E", "D", "C", "B", "A")

I will get another list from the server. For example:-

val b = listOf("A", "G", "C")

List from the server may contain fewer elements or more elements but will not contain elements other than the first list.

So, after sorting output should be like

// G, C, A

5
  • Have you tried anything so far? Commented Nov 12, 2019 at 12:01
  • You just want to sort b ? Commented Nov 12, 2019 at 12:04
  • Yeah, @The_ehT, Need to sort server list (list b) based on list a Commented Nov 12, 2019 at 12:08
  • I don't think "sort" is the right word here. You want to filter your source list (a) by keeping only elements present in your target list that you get from the server (b). Commented Nov 12, 2019 at 12:18
  • That's another way to look at it. What if he wants to sort b based on order of elements at a. Commented Nov 12, 2019 at 12:19

4 Answers 4

6

You can use map and sorted to achieve that easily on the condition that a do not have repetition -

val a = listOf("G", "F", "E", "D", "C", "B", "A")
val b = listOf("A", "G", "C")
val there = b.map{ v -> a.indexOf(v)}.sorted().map{v -> a[v]}
println(there)

Output:: [G, C, A]

Alternate sorter way as pointed by @jsamol in comment -

val there = b.sortedBy { a.indexOf(it) }
Sign up to request clarification or add additional context in comments.

3 Comments

There is no need to map b twice. You can just use sortedBy: b.sortedBy { a.indexOf(it) }
Oh yes, that's better. I completely forgot sortedBy. thanks for pointing out.
I don't agree the shorter code is necessary better: sorting in general makes O(N*logN) comparisons, where N is the number of items in the sorted list, and for each comparison it needs to perform two a.indexOf(it) operations, that themselves are O(M), where M is the number of elements in the first list. So the resulting complexity would be O(N*logN*2M). And the original approach with mapping indices has the complexity of only O(N*(M + logN + 1)). For large lists this difference can be significant.
5

You are not trying to sort, you are trying to filter

fun filterByServer(server: List<String>, local: List<String>)
        = local.filter { value -> server.contains(value) }

filter takes a predicate in this case if your local value is contained on the server list

2 Comments

Is toMutableList() needed here?
@LeonardoHerrera you are right is not because the filter method will return another list, my mistake is because I was writing the method using arrays and then realize it was a list, got confused with the title, thanks it should be updated now
1

You can create a custom comparator based on the indices of letters in the a list. Then use the List.sortedWith function to sort the b list. e.g.

val a = listOf("G", "F", "E", "D", "C", "B", "A")
val b = listOf("A", "G", "C")
val indexedA: Map<String, Int> = a.mapIndexed { index, s -> s to index }.toMap()
val comparator = object: Comparator<String> {
    override fun compare(s1: String, s2: String): Int {
        val i1 = indexedA[s1]
        val i2 = indexedA[s2]
        return if (i1 == null || i2 == null) throw RuntimeException("unable to compare $s1 to $s2")
        else i1.compareTo(i2)
    }
}
val c = b.sortedWith(comparator)
System.out.println(c)

I've converted the list a to a map: Letter to Index as an optimization.

2 Comments

Why not use b.sortedBy { indexedA[it] }?
yup, sortedBy looks like a better (shorter) solution
1

If I understand the requirement, what we're really doing here is filtering the first list, according to whether its elements are in the second.  So another approach would be to do that explicitly.

val a = listOf("G", "F", "E", "D", "C", "B", "A")
val b = listOf("A", "G", "C").toSet()   // or just setOf(…)
val there = a.filter{ it in b }

There's a bit more processing in creating the set, but the rest is faster and scales better, as there's no sorting or scanning, and checking for presence in a set is very fast.

(In fact, that would work fine if b were a list; but that wouldn't perform as well for big lists.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.