Scala Converting Each Array Element to String and Splitting - arrays

I have an array loaded in, and been playing around in the REPL but can't seem to get this to work.
My array looks like this:
record_id|string|FALSE|1|
offer_id|decimal|FALSE|1|1,1
decision_id|decimal|FALSE|1|1,1
offer_type_cd|integer|FALSE|1|1,1
promo_id|decimal|FALSE|1|1,1
pymt_method_type_cd|decimal|FALSE|1|1,1
cs_result_id|decimal|FALSE|1|1,1
cs_result_usage_type_cd|decimal|FALSE|1|1,1
rate_index_type_cd|decimal|FALSE|1|1,1
sub_product_id|decimal|FALSE|1|1,1
campaign_id|decimal|FALSE|1|1,1
When I run my command:
for(i <- 0 until schema.length){
val convert = schema(i).toString;
convert.split('|').drop(2);
println(convert);
}
It won't drop anything. It also is not splitting it on the |

Strings are immutable, and so split and drop don't mutate the string - they return a new one.
You need to capture the result in a new val
val split = convert.split('|').drop(2);
println(split.mkString(" "));

Consider also defining a lambda function for mapping each item in the array, where intermediate results are passed on with the function,
val res = schema.map(s => s.toString.split('|').drop(2))

Related

Rails Ransack, initialize from front end as an array

In the React front end, the ransack parameter is initialized like so:
const statusFilter = 'ransack[status_in]=incomplete';
In the backend, I've got
#params["ransack"]&.each do |filter, value|
so that the first line produces
filter = "status_in"
value = "incomplete"
Everywhere else in the app after initializing, the status_in parameter is used as an array, so that multiple statuses can be selected. So I would like to always treat this parameter as an array, not a string, if possible.
My desired output:
value = ["incomplete"]
I've tried
const statusFilter = "ransack[status_in]=['incomplete']";
But that results in
value = "['incomplete']"
I could probably just check whether the type is a string on the first usage, and then convert it to an array. Something like:
value = [value] if value.class == String
But it seems like there should be a way to accomplish this by slightly changing the front so that I don't need to add another line in the back.

How to get a specific index value in array by using map and stream in Kotlin?

I want to get a list of String in ArrayList<Array<String>> by using stream() and map in Kotlin.
Each Array<String> of my arrayList has 3 values and I want to get the first index value and the last index value of each array.
This is my code:
fun main(args: Array<String>) {
val result: List<String>
val obj1 = arrayOf("fruit", "Mangue", "Africa")
val obj2 = arrayOf("Milk", "Soja", "Europ")
val obj3 = arrayOf("Meat", "cochon","Asia")
val myArrayList: ArrayList<Array<String>> = ArrayList<Array<String>>(3)
val myList: MutableList<Array<String>> = mutableListOf<Array<String>>()
myList.add(obj1)
myList.add(obj2)
myList.add(obj3)
myArrayList.addAll(myList)
result = myArrayList.stream().map{it -> ("${it[0]}-${it[2]}")}.toList()
println("ArrayList of objects :")
println(myArrayList)
println("my list of String result")
println(result)
}
I want to have this list of String in my result:
[fruit-africa,milk-Europ,Meat-Asia]
Also, when I print myArrayList, I have a bad result:
ArrayList of objects :
[[Ljava.lang.String;#5caf905d, [Ljava.lang.String;#27716f4, [Ljava.lang.String;#8efb846]
How can I do it, please?
Your Question
When I run your code, this is the output I see:
ArrayList of objects :
[[Ljava.lang.String;#5b480cf9, [Ljava.lang.String;#6f496d9f, [Ljava.lang.String;#723279cf]
my list of String result
[fruit-Africa, Milk-Europ, Meat-Asia]
And in your question, you have:
I want to have this list of String in my result:
[fruit-africa,milk-Europ,Meat-Asia]
So, it looks like you already have the output you want for result. The only difference from the actual output is the lack of a space after each comma. If you don't want that space, then use joinToString to customize the output:
println(result.joinToString(",", "[", "]"))
As for:
[[Ljava.lang.String;#5b480cf9, [Ljava.lang.String;#6f496d9f, [Ljava.lang.String;#723279cf]
You see that output because arrays don't override the toString() function, and therefore use the default implementation. In Kotlin, you can use contentToString() to get similar output as you see when printing a List.
println(myArrayList.joinToString(", ", "[", "]") { it.contentToString() })
So, here is the updated code with the above changes:
fun main(args: Array<String>) {
val result: List<String>
val obj1 = arrayOf("fruit", "Mangue", "Africa")
val obj2 = arrayOf("Milk", "Soja", "Europ")
val obj3 = arrayOf("Meat", "cochon","Asia")
val myArrayList: ArrayList<Array<String>> = ArrayList<Array<String>>(3)
val myList: MutableList<Array<String>> = mutableListOf<Array<String>>()
myList.add(obj1)
myList.add(obj2)
myList.add(obj3)
myArrayList.addAll(myList)
result = myArrayList.stream().map{it -> ("${it[0]}-${it[2]}")}.toList()
println("ArrayList of objects :")
println(myArrayList.joinToString(", ", "[", "]") { it.contentToString() })
println("my list of String result")
println(result.joinToString(",", "[", "]"))
}
Which gives this output:
ArrayList of objects :
[[fruit, Mangue, Africa], [Milk, Soja, Europ], [Meat, cochon, Asia]]
my list of String result
[fruit-Africa,Milk-Europ,Meat-Asia]
Potential Improvements
With all that said, there are a few things you can simplify in your code:
This is a minor point, but since you don't use the args parameter you can actually omit it.
Your myList is not necessary; you can add your arrays directly to myArrayList.
Given the small number of elements in each array, and the small number of arrays, you can actually create the List<Array<String>> and populate it with a single listOf.
For variable types, you should prefer using List, the interface, rather than ArrayList, the implementation. This is known as "programming to an interface". Preferring List also means better use of listOf and mutableListOf, which are the idiomatic ways of creating lists in Kotlin.
You should prefer using List over arrays. In other words, create a List<List<String>> instead of a List<Array<String>>.
Lists do override the toString() method, providing readable output. Also, lists have better API support and work better with generics.
You don't need to use stream(). Kotlin provides many extension functions for arrays and Iterables, one of those being map which returns a List. Yes, these transformation functions are eagerly evaluated, unlike with streams, but given you're only performing one transfomration this doesn't really matter (in fact, the stream is likely less performant).
See kotlin.collections for the available built-in extension functions.
Given you want the first and last elements of each array, I would use first() and last().
Here is the simplified code (I added explicit types to make it clearer what the variables reference):
fun main() {
val lists: List<List<String>> = listOf(
listOf("Fruit", "Mangue", "Africa"),
listOf("Milk", "Soja", "Europe"),
listOf("Meat", "Cochon", "Asia")
)
println("List of lists of strings:")
println(lists)
val result: List<String> = lists.map { "${it.first()}-${it.last()}" }
println("Result:")
println(result)
}
Output:
List of Arrays:
[[Fruit, Mangue, Africa], [Milk, Soja, Europe], [Meat, Cochon, Asia]]
Result:
[Fruit-Africa, Milk-Europe, Meat-Asia]

Ordering when using scala.collection.Searching

I have an Array of [Long, Q] and would like to make a binary search on it. I tried below :
import scala.collection.Searching._
class Q (val b:Double, val a:Double)
val myArray = Array(5L -> new Q(1,2), 6L-> new Q(6,9), 7L-> new Q(7,6))
val i = myArray.search(6L).insertionPoint
but had this error
No implicit Ordering defined for Any
Unspecified value parameter ord.
I understand that I need to specify an odering rule for this collection Array[(Long,Q)] but can't figure this out myself.
Please help
Signature of search is search[B >: A](elem: B)(implicit ord: Ordering[B]). You've got an array of type [Long, Q]. So in order for the compiler to infer Ordering correctly, you'd have to invoke search like that:
myArray.search(6L-> q/*Q(6,9)*/)(Ordering.by(_._1)) //ordering by the first value in a tuple.
and what you're doing is: myArray.search(6L). If I understand correctly what you're trying to do, it's probably to find both value and position in the array.
You could solve it by using two separate data structures:
keys could be stored in the array, like this:
val myArray = Array(5L, 6L, 7L).toList
myArray.search(6L).insertionPoint
and if you'd need values, you could use map which would work as a dictionary:
val dictionary = Map(
5L -> new Q(1,2),
6L-> new Q(6,9),
7L-> new Q(7,6)
)
EDIT:
Actually, I noticed something like that would work:
val dummy = new Q(0,0) //any instance of Q
myArray.search(6L-> dummy)(Ordering.by(_._1)).insertionPoint //1
It works since for lookup of the insertion point Ordering is used and no equality test is performed.

Kotlin - Find matching objects in array

Let's say I have an array of strings and I want to get a list with objects that match, such as:
var locales=Locale.getAvailableLocales()
val filtered = locales.filter { l-> l.language=="en" }
except, instead of a single value I want to compare it with another list, like:
val lang = listOf("en", "fr", "es")
How do I do that? I'm looking for a one-liner solution without any loops. Thanks!
Like this
var locales = Locale.getAvailableLocales()
val filtered = locales.filter { l -> lang.contains(l.language)}
As pointed out in comments, you can skip naming the parameter to the lambda, and use it keyword to have either of the following:
val filtered1 = locales.filter{ lang.contains(it.language) }
val filtered2 = locales.filter{ it.language in lang }
Just remember to have a suitable data structure for the languages, so that the contains() method has low time complexity like a Set.

Is there a way to convert a struct into an array without using a loop?

I'm curious, is there another way to convert a struct into an array in Coldfusion without looping over it? I know it can be done this way if we use a for in loop:
local.array = [];
for (local.value in local.struct)
{
arrayAppend(local.array, local.value);
}
Does StructKeyArray suit your requirements?
Description
Finds the keys in a ColdFusion
structure.
If you are trying to maintain order in your structure you could always use a Java LinkedHashMap like so:
cfmlLinkedMap = createObject("Java", "java.util.LinkedHashMap").init();
cfmlLinkedMap["a"] = "Apple";
cfmlLinkedMap["b"] = "Banana";
cfmlLinkedMap["c"] = "Carrot";
for(key in cfmlLinkedMap){
writedump(cfmlLinkedMap[key]);
}
You could also do the same thing in a more "java" way not sure why you'd want to but its always an option:
//no need to init
linkedMap = createObject("Java", "java.util.LinkedHashMap");
//java way
linkedMap.put("d","Dragonfruit");
linkedMap.put("e","Eggplant");
linkedMap.put("f","Fig");
//loop through values
iterator = linkedMap.entrySet().iterator();
while(iterator.hasNext()){
writedump(iterator.next().value);
}
//or
//loop through keys
iterator = linkedMap.keySet().iterator();
while(iterator.hasNext()){
writedump(linkedMap.get(iterator.next()));
}
Just remember that the keys are case SeNsItIvE!
In Coldfusion 10 or Railo 4, if you want an array of values (instead of keys), you can use the Underscore.cfc library like so:
_ = new Underscore();// instantiate the library
valueArray = _.toArray({first: 'one', second: 'two'});// returns: ['one','two']
Note: Coldfusion structures are unordered, so you are not guaranteed to have any specific order for the values in the resulting array.
(Disclaimer: I wrote Underscore.cfc)

Resources