How to swap elements in MutableList in Kotlin? - list

I have a list with data that I pull from api. However, I need to make changes on this list (movieList). I need to swap the element at index 0 with the element at index 1. For example:
list[0] = movieA,
list[1] = movieB
then
list[0] = movieB,
list[1] = movieA
The class I intend to do these operations is below:
data class MovieListDto(
val docs: List<Movie>,
val limit: Int,
val offset: Int,
val page: Int,
val pages: Int,
val total: Int
)
fun MovieListDto.MovieListDtoToMovieList(): List<Movie> {
val movieList = mutableListOf<Movie>()
for (movie in docs) {
if (movie._id == "5cd95395de30eff6ebccde5c" ||
movie._id == "5cd95395de30eff6ebccde5b" ||
movie._id == "5cd95395de30eff6ebccde5d"
) {
movieList.add(movie)
}
}
return movieList
}
How can I do this?

You could use a simple extension function for that:
fun <T> MutableList<T>.swap(index1: Int, index2: Int){
val tmp = this[index1]
this[index1] = this[index2]
this[index2] = tmp
}
it can be use like this:
list.swap(0, 1)

val temp = movieList[0]
movieList[0] = movieList[1]
movieList[1] = temp

I think you can use also scope function to swap
movieList[0] = movieList[1].also { movieList[1] = movieList[0] }

use Collections.swap() method in JDK
see https://developer.android.com/reference/java/util/Collections#swap(java.util.List%3C?%3E,%20int,%20int)

Related

Dart print multiple list item at once

How can I type something like "print(list[1,4]);" in Dart?
For example:
int main() {
var products = new List(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products[1,3]); // I want to see 'Mouse,Monitor'
}
This is not directly supported in the SDK but you can easily make a extension on e.g. List to add this feature:
void main() {
final products = List<String>(5);
products[0] = "Laptop";
products[1] = "Mouse";
products[2] = "Keyboard";
products[3] = "Monitor";
products[4] = "Microphone";
print(products[1]); // Mouse
print(products.selectMultiple([1,3]).join(',')); // Mouse,Monitor
}
extension MultiSelectListExtension<E> on List<E> {
Iterable<E> selectMultiple(Iterable<int> indexes) sync* {
for (final index in indexes) {
yield this[index];
}
}
}
You can't make it so [1,3] (as in you own example) would be valid since the [] operator does only allow one argument. So instead, we need to make a method which takes our requested indexes as argument.

Scala function takes 2 hours with 2 million values

Would be grateful if any ideas to speed it up!
case class Pair(aa:String, bb:String)
case class OutputRow(bb:String, aa:String, bb_2:String, aa_2:String)
def startSearch(
_1_sorted: Array[Pair] ,
_2_hashmap: HashMap[String, String] ) : ArrayBuffer[OutputRow] = {
var outputTableListBuffer = ArrayBuffer[OutputRow]()
var searchComparisionFlag = false
var storeMain = Pair("0","0") //Initialize with Dummy data
var i = 0
def search(xxxx_1: Pair): Unit = {
if (searchComparisionFlag==true) {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
outputTableListBuffer.append(OutputRow(storeMain.aa, storeMain.bb,_2_xxxx, xxxx_1.aa))
i = i + 1
if (i % 1000 == 0) println("In recursive search storeMain: ", storeMain)
var storePair = Pair(_2_xxxx,xxxx_1.aa)
search(storePair)
} else {
searchComparisionFlag = false
return
}
} else {
var _2_exists = _2_hashmap.exists(_._1 == xxxx_1.aa)
if (_2_exists) {
val _2_xxxx = _2_hashmap(xxxx_1.aa)
searchComparisionFlag = true
outputTableListBuffer.append(OutputRow(xxxx_1.aa, xxxx_1.bb,_2_xxxx, xxxx_1.aa))
var store = Pair(_2_xxxx,xxxx_1.aa)
search(store)
}
}
}
_1_sorted.foreach{ aa_1 =>
val store = Pair(aa_1.aa, aa_1.bb)
storeMain = store
search(store)
}
outputTableListBuffer
}
The above function takes 2 hours with 1 million values in _1_sorted and with a good 1 Million lookup in the hashmap.
Any ideas to speed this up?
This is a recursive logic function
The biggest problem is this:
_2_hashmap.exists(_._1 == xxxx_1.aa)
This is checking every single element of the hashmap on every call. Instead, use get:
_2_hashmap.get(xxxx_1.aa) match {
Some(_2_xxxx) => // Found
???
None => // Not found
???
}
Other code issues:
Don't use return
Pass flags down through recursive call rather than using global var
Use val wherever possible
Don't start variable names with _

Kotlin declare nested array

How can nested lists be declared in Kotlin?
I'm looking for something in the form of:
var nestedList:List = [1,[2,[3,null,4]],[null],5]
so that I can flatten it later on (result should be nestedList = [1, 2, 3, 4, 5]).
If you have nested arrays structure (for instance, val array: Array<Array<out Int?>> = arrayOf(arrayOf(1), arrayOf(2), arrayOf(3, null, 4))), you can just use flatten extension method:
println(array.flatten().filterNotNull())
All common collections can't maintain variable layers count, so with them you can make only something like Andrey Ilyunin wrote - val array: Array<Array<out Int?>>.
But I wrote class structure to help you with your goal. It is no another collection and you can't work with it like it is, but it can make any layers amount you want. It is totally generic, so you can put there not only Int.
First of all, we start with NestedArrayItem class, which represents single item or one more nested array:
class NestedArrayItem<T> {
private val array: ArrayList<NestedArrayItem<T>>?
private val singleItem: T?
constructor(array: ArrayList<NestedArrayItem<T>>) {
this.array = array
singleItem = null
}
constructor(singleItem: T?) {
this.singleItem = singleItem
array = null
}
fun asSequence(): Sequence<T?> =
array?.asSequence()?.flatMap { it.asSequence() } ?:
sequenceOf(singleItem)
override fun toString() =
array?.joinToString(prefix = "[", postfix = "]") ?:
singleItem?.toString() ?: "null"
}
Then class NestedArray that is just like top level container for all the layers:
class NestedArray<T> {
private val array: ArrayList<NestedArrayItem<T>> = arrayListOf()
fun add(value: T?) {
array.add(NestedArrayItem(value))
}
fun addNested(nestedArray: NestedArray<T>) {
array.add(NestedArrayItem(nestedArray.array))
}
fun flatten(): ArrayList<T?> = array.asSequence()
.flatMap { it.asSequence() }
.toCollection(arrayListOf())
override fun toString() = array.joinToString(prefix = "[", postfix = "]")
}
And to make it easier to write values I additionally wrote builder class for that:
class NestedArrayBuilder<T> private constructor(private val result: NestedArray<T>){
constructor(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit) : this(NestedArray()) {
NestedArrayBuilder(result).apply(fillNestedBuilder)
}
fun add(value: T?): NestedArrayBuilder<T> {
result.add(value)
return this
}
fun addArray(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit): NestedArrayBuilder<T> {
val nestedResult = NestedArray<T>()
val nestedArray = NestedArrayBuilder(nestedResult).apply(fillNestedBuilder)
.build()
result.addNested(nestedArray)
return this
}
fun build() = result
}
That's it! You can use it. I put here example how to use it:
val array = NestedArrayBuilder<Int> {
add(1)
addArray {
add(2)
addArray {
add(3)
add(null)
add(4)
}
}
addArray {
add(null)
}
add(5)
}.build()
assertEquals("[1, [2, [3, null, 4]], [null], 5]", array.toString())
assertEquals(arrayListOf(1, 2, 3, null, 4, null, 5), array.flatten())

Display a chunked items list in Java 8

With the following code:
public class Main {
public static void main(String[] args) {
final List<Integer> items =
IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());
final String s = items
.stream()
.map(Object::toString)
.collect(Collectors.joining(","))
.toString()
.concat(".");
System.out.println(s);
}
}
I get:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.
What I would like to do, is to break the line every 10 items, in order to get:
0,1,2,3,4,5,6,7,8,9,
10,11,12,13,14,15,16,17,18,19,
20,21,22,23.
I have try a lot of things after googling without any success !
Can you help me ?
Thanks,
Olivier.
If you're open to using a third-party library, the following will work using Eclipse Collections Collectors2.chunk(int).
String s = IntStream.rangeClosed(0, 23)
.boxed()
.collect(Collectors2.chunk(10))
.collectWith(MutableList::makeString, ",")
.makeString("", ",\n", ".");
The result of Collectors2.chunk(10) will be a MutableList<MutableList<Integer>>. At this point I switch from the Streams APIs to using native Eclipse Collections APIs which are available directly on the collections. The method makeString is similar to Collectors.joining(). The method collectWith is like Stream.map() with the difference that a Function2 and an extra parameter are passed to the method. This allows a method reference to be used here instead of a lambda. The equivalent lambda would be list -> list.makeString(",").
If you use just Eclipse Collections APIs, this problem can be simplified as follows:
String s = Interval.zeroTo(23)
.chunk(10)
.collectWith(RichIterable::makeString, ",")
.makeString("", ",\n", ".");
Note: I am a committer for Eclipse Collections.
If all you want to do is process these ascending numbers, you can do it like
String s = IntStream.rangeClosed(0, 23).boxed()
.collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
Collectors.mapping(Object::toString, Collectors.joining(","))))
.values().stream()
.collect(Collectors.joining(",\n", "", "."));
This solution can be adapted to work on an arbitrary random access list as well, e.g.
List<Integer> items = IntStream.rangeClosed(0, 23).boxed().collect(Collectors.toList());
String s = IntStream.range(0, items.size()).boxed()
.collect(Collectors.groupingBy(i -> i/10, LinkedHashMap::new,
Collectors.mapping(ix -> items.get(ix).toString(), Collectors.joining(","))))
.values().stream()
.collect(Collectors.joining(",\n", "", "."));
However, there is no simple and elegant solution for arbitrary streams, a limitation which applies to all kind of tasks having a dependency to the element’s position.
Here is an adaptation of the already linked in the comments Collector:
private static Collector<String, ?, String> partitioning(int size) {
class Acc {
int count = 0;
List<List<String>> list = new ArrayList<>();
void add(String elem) {
int index = count++ / size;
if (index == list.size()) {
list.add(new ArrayList<>());
}
list.get(index).add(elem);
}
Acc merge(Acc right) {
List<String> lastLeftList = list.get(list.size() - 1);
List<String> firstRightList = right.list.get(0);
int lastLeftSize = lastLeftList.size();
int firstRightSize = firstRightList.size();
// they are both size, simply addAll will work
if (lastLeftSize + firstRightSize == 2 * size) {
System.out.println("Perfect!");
list.addAll(right.list);
return this;
}
// last and first from each chunk are merged "perfectly"
if (lastLeftSize + firstRightSize == size) {
System.out.println("Almost perfect");
int x = 0;
while (x < firstRightSize) {
lastLeftList.add(firstRightList.remove(x));
--firstRightSize;
}
right.list.remove(0);
list.addAll(right.list);
return this;
}
right.list.stream().flatMap(List::stream).forEach(this::add);
return this;
}
public String finisher() {
return list.stream().map(x -> x.stream().collect(Collectors.joining(",")))
.collect(Collectors.collectingAndThen(Collectors.joining(",\n"), x -> x + "."));
}
}
return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}
And usage would be:
String result = IntStream.rangeClosed(0, 24)
.mapToObj(String::valueOf)
.collect(partitioning(10));

Get Max value from List<myType>

I have List List<MyType>, my type contains Age and RandomID
Now I want to find the maximum age from this list.
What is the simplest and most efficient way?
Assuming you have access to LINQ, and Age is an int (you may also try var maxAge - it is more likely to compile):
int maxAge = myTypes.Max(t => t.Age);
If you also need the RandomID (or the whole object), a quick solution is to use MaxBy from MoreLinq
MyType oldest = myTypes.MaxBy(t => t.Age);
Okay, so if you don't have LINQ, you could hard-code it:
public int FindMaxAge(List<MyType> list)
{
if (list.Count == 0)
{
throw new InvalidOperationException("Empty list");
}
int maxAge = int.MinValue;
foreach (MyType type in list)
{
if (type.Age > maxAge)
{
maxAge = type.Age;
}
}
return maxAge;
}
Or you could write a more general version, reusable across lots of list types:
public int FindMaxValue<T>(List<T> list, Converter<T, int> projection)
{
if (list.Count == 0)
{
throw new InvalidOperationException("Empty list");
}
int maxValue = int.MinValue;
foreach (T item in list)
{
int value = projection(item);
if (value > maxValue)
{
maxValue = value;
}
}
return maxValue;
}
You can use this with:
// C# 2
int maxAge = FindMaxValue(list, delegate(MyType x) { return x.Age; });
// C# 3
int maxAge = FindMaxValue(list, x => x.Age);
Or you could use LINQBridge :)
In each case, you can return the if block with a simple call to Math.Max if you want. For example:
foreach (T item in list)
{
maxValue = Math.Max(maxValue, projection(item));
}
int max = myList.Max(r => r.Age);
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.max.aspx
var maxAge = list.Max(x => x.Age);
thelist.Max(e => e.age);
Easiest way is to use System.Linq as previously described
using System.Linq;
public int GetHighestValue(List<MyTypes> list)
{
return list.Count > 0 ? list.Max(t => t.Age) : 0; //could also return -1
}
This is also possible with a Dictionary
using System.Linq;
public int GetHighestValue(Dictionary<MyTypes, OtherType> obj)
{
return obj.Count > 0 ? obj.Max(t => t.Key.Age) : 0; //could also return -1
}
Simplest is actually just Age.Max(), you don't need any more code.
How about this way:
List<int> myList = new List<int>(){1, 2, 3, 4}; //or any other type
myList.Sort();
int greatestValue = myList[ myList.Count - 1 ];
You basically let the Sort() method to do the job for you instead of writing your own method. Unless you don't want to sort your collection.