The value of NumberPicker doesn't change - kotlin

I'm a beginner in android and Kotlin.
I want to get string values I set as displayedValues from NumberPicker.
I tried, but It only returns Int numbers.
After some search, I found a question Formatted value of NumberPicker disappears onClick which might be the solution to my problem.
But I'm beginner and never studied java, so I couldn't apply it to my code. I need your help to figure out whether my code is correct and if it is, I hope to get a solution which can be applied to kotlin
Thankyou!
val pickers = arrayListOf(picker1,picker2,picker3,picker4,picker5,picker6,picker7)
for (picker in pickers) {
picker.displayedValues = arrayOf(
"0", "30", "40", "50", "60", "1시간", "1시간 30분", "2시간", "2시간 30분", "3시간", "3시간 30분", "4시간",
"4시간 30분", "5시간"
)
picker.minValue = 0
picker.maxValue = 13
picker.setFormatter { num -> picker.displayedValues[num] }

The translation of the answer there to Kotlin is
// do this outside the loop because it doesn't depend on picker
val f = NumberPicker::class.java.getDeclaredField("mInputText")
f.setAccessible(true)
// inside the loop
val inputText = f.get(picker) as EditText
inputText.setFilters(arrayOf())
(it's surrounded by try-catch which you can do in Kotlin as well if you want but the particular catch there is useless; and if you do it should be outside the for loop).

Related

Why am I geting a blank when I run this string funtion in Kotlin?

So I was solving a problem that required me to put unique characters in a string without using a data structure.
fun main(){
val s1 = "fhfnfnfjuw"
val s2 = "Osayuki"
val s3 = "Raymond"
val s4 = "Aseosa"
uniqueChar(s1)
}
fun uniqueChar(s: String){
val updatedString = ""
s.forEach {c ->
if (!updatedString.contains(c)){
updatedString.plus(c)
}
}
println(updatedString)
}
And getting this error
I'm not sure what's going on and why I'm getting a blank. I'm sure it's an easy fix, but I can't see it. Any help is appreciated.
updatedString.plus(c) does not change updatedString. It creates a new string, including the character c. Since you don't do anything with that, the new string goes...nowhere.
Instead, you probably wanted updatedString = updatedString.plus(c) -- or something better with StringBuilder, but that's the closest version to your code.

In Kotlin, How to groupBy only subsequent items? [duplicate]

This question already has answers here:
Split a list into groups of consecutive elements based on a condition in Kotlin
(4 answers)
Closed 7 months ago.
I want to groupBy a list of items by its value, but only if subsequent, and ignore grouping otherwise:
input:
val values = listOf("Apple", "Apple", "Grape", "Grape", "Apple", "Cherry", "Cherry", "Grape")
output: {"Apple"=2, "Grape"=2, "Apple"=1, "Cherry"=2, "Grape"=1}
There's no built in option for this in Kotlin - it has to be custom, so there are many different options.
Because you need to keep track of the previous element, to compare the current one against, you need to have some sort of state. To achieve this you could use zipWithNext or windowed to group elements. Or use fold and accumulate the values into a list - removing and adding the last element depending on whether there's a break in the sequence.
To try and keep things a bit more clearer (even if it breaks the norms a bit) I recommend using vars and a single loop. I used the buildList { } DSL, which creates a clear scope for the operation.
val result: List<Pair<String, Int>> = buildList {
var previousElement: String? = null
var currentCount: Int = 0
// iterate over each incoming value
values.forEach { currentElement: String ->
// currentElement is new - so increment the count
currentCount++
// if we have a break in the sequence...
if (currentElement != previousElement) {
// then add the current element and count to our output
add(currentElement to currentCount)
// reset the count
currentCount = 0
}
// end this iteration - update 'previous'
previousElement = currentElement
}
}
Note that result will match the order of your initial list.
You cloud use MultiValueMap which can has duplicated keys. Since there is no native model you should implement yourself or use the open-source library.
Here is a reference.
Map implementation with duplicate keys
For comparison purposes, here's a short but inefficient solution written in the functional style using fold():
fun <E> List<E>.mergeConsecutive(): List<Pair<E, Int>>
= fold(listOf()) { acc, e ->
if (acc.isNotEmpty() && acc.last().first == e) {
val currentTotal = acc.last().second
acc.dropLast(1) + (e to currentTotal + 1)
} else
acc + (e to 1)
}
The accumulator builds up the list of pairs, incrementing its last entry when we get a duplicate, or appending a new entry when there's a different item. (You could make it slightly shorter by replacing the currentTotal with a call to let(), but that would be even harder to read.)
It uses immutable Lists and Pairs, and so has to create a load of temporary ones as it goes — which makes this pretty inefficient (𝒪(𝑛²)), and I wouldn't recommend it for production code. But hopefully it's instructive.

How do I pull entries from an ArrayList at random in Kotlin?

This is my first Kotlin project. I am learning as I go and I have reached a roadblock.
I have an ArrayList of questions that I want to pull into that app in a random order. I've tried assigning the .random to the point where the question is assigned (right now it is set to CurrentPosition-1) but that only randomized the question and didn't pull the correct answers along with the questions.
How do I either bundle the answers to the question or is there a better way to get the questions to shuffle in order? I plan on having 50+ questions but only 10 will show each time the test is taken. I don't want the same 10 questions showing each time the user opens the test.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz_questions)
mQuestionsList=Constants.getQuestions()
setQuestion()
}
private fun setQuestion(){
val question = mQuestionsList!![mCurrentPosition-1]
defaultOptionsView()
if(mCurrentPosition == mQuestionsList!!.size){
submitBtn.text = "Finish"
}else{
submitBtn.text = "Submit"
}
progressBar.progress = mCurrentPosition
tv_progress.text = "$mCurrentPosition" + "/" + progressBar.max
tv_question.text = question!!.question
test_image.setImageResource(question.image)
tvOptionOne.text = question.optionOne
tvOptionTwo.text = question.optionTwo
tvOptionThree.text = question.optionThree
tvOptionFour.text = question.optionFour
}
private fun defaultOptionsView(){
val options = ArrayList<TextView>()
options.add(0, tvOptionOne)
options.add(1, tvOptionTwo)
options.add(2, tvOptionThree)
options.add(3, tvOptionFour)
Here is my Array
object Constants{
const val TOTAL_QUESTIONS: String = "total_questions"
const val CORRECT_ANSWERS: String = "correct_answers"
fun getQuestions(): ArrayList<Question>{
val questionsList = ArrayList<Question>()
val q1 = Question(
R.drawable.questionmark,
1,
"Who is Regional Manager of\n Dunder Mifflin Scranton?",
"Michael",
"Jim",
"Pam",
"Dwight",
1,
)
I appreciate any help at all. Thank you in advance.
list.shuffled().take(10) And make your mQuestionsList property type List instead of ArrayList since you don’t need to modify it after retrieval. You should also probably make it lateinit or initialize it at its declaration site so you won’t have to make the type nullable and have to resort to !!, which is generally a code smell. So I would declare it as var mQuestionsList: List<Question> = emptyList() and whenever you want new values do mQuestionsList = Constants.getQuestions().shuffled().take(10).

How can I translate this Kotlin code into a better one using high order functions instead of a simple for

I have this function that receives a barcode and looks for a product in a list that has the same barcode. The split( ",") is because there are some products that have more than one barcode written like this: ("barcode1,barcode2")
Could someone help me get a better code using high order functions rather than this for loop?
fun Product.byBarcode(barcode: String?) : Product? {
val productsList = Realm.getDefaultInstance().where(Product::class.java).findAll().toMutableList()
var foundProduct : Product? = null
for (it in productsList){
if ( it.barcode.split(",").contains(barcode)){
foundProduct = it
break
}
}
return foundProduct
}
You can use find
foundProduct = productList.find{ it.barcode.split(',').contains(barcode) }
also I don't think split is really required, in that case
foundProduct = productList.find{ it.barcode.contains(barcode) }

how to set multiple kotlin variables in one line

I want to fill two variables in the same line, but I don't know the best way to do it at kotlin
var a:String? = null
var b:String? = null
a, b = "Text"
Not possible in Kotlin (unless you are ready to resort to some contrived constructs with repetition as described in other answers and comments). You cannot even write
a = b = "Text"
because weirdly enough, assignments are not expressions in Kotlin (as opposed to almost everything else like if, return, throw, swicth, etc., which are expressions in Kotlin, but not in Java, for example).
So, if you want to assign exactly the same value without repetition (of the assigned value), you'll have to write
a = "Text"
b = a
Note, that there is also an also function (pun intended), so technically you can write the following if you really want to stay on one line
a = "Text".also { b = it }
but I doubt it is really worth it.
var a: String? = null; var b: String? = null
or
var (a: String?, b: String?) = null to null
But please don't ever do so
Simply create an inline array, iterate through and assign values.
arrayListOf(a, b, c, d).forEach { it = "Text" }