way to Check null objects in json api array - kotlin

I'm trying a lot of things but i still can not figure out a way to Check if an object is null.
This is the Api response
Api response
The problem sometimes the object shortname Doesn't exist in the teamInfo
so there will be just "name" and "img" . i want to show some other text if shortname Doesn't exist in teaminfo.
I've tried something like:
Text(
text = if(data.teamInfo[1].shortname != null){data.teamInfo[1].shortname}
else{data.teams[1]},
modifier = Modifier
.weight(1f)
.padding(5.dp)
.align(Alignment.CenterVertically),
fontWeight = FontWeight.Bold,
maxLines = 1
)

Firstly, I see you are hardcoding the array index always to be 1. Is that right for your case?
The relevant part is this
text = if (data.teamInfo[1].shortname != null) {
data.teamInfo[1].shortname
} else {
data.teams[1]
},
Your null check is valid, the fragment of the JSON response you gave doesn't seem to have a teams array so the second part may not work/compile/produce a non-null. You do say each teaminfo will have a name so try this first
text = if (data.teamInfo[1].shortname != null) {
data.teamInfo[1].shortname
} else {
data.teamInfo[1].name
},
And you can simply this with the "Elvis" operator
text = data.teamInfo[1].shortname ?: data.teamInfo[1].name

Related

How to check user name and last name length in one textfield in android jetpack compose?

There is an outlinedtextfield where the user enters his/her name and surname, and this outlinetextfield enters the user name and surname, but if the user's name and surname are less than 3 characters, I want to make the border of the outlinetextfield red, but I couldn't figure out how to do this control because space intervened.
for example :
a(space)b wrong
jac(space)jac correct
tony(space)stark correct
this is my example code:
OutlinedTextField(
value = state.name,
onValueChange = { onChangeName(it) },
modifier = Modifier
.fillMaxWidth(),
shape = RoundedCornerShape(25.dp),
label = {
Text(
text = "name and lastname",
fontSize = 14.sp,
color = Color.White
)
},
colors = TextFieldDefaults.outlinedTextFieldColors(
focusedBorderColor = if (state.name.length < 7) Color.Red else DefaultDYTColor,
unfocusedBorderColor = Color.Transparent
)
)
When I do it this way, it accepts it as correct even if I type 7 characters without spaces, but it should not be like this.
for example:
tonystark
According to the code I wrote, this is correct because it is greater than 7 characters
How to achieve this issue ? Do you have any suggestion or solve ?
This is just an algorithmic problem, you can solve it like this:
fun isValidName(name: String): Boolean {
// split name on each space and filter out those that are blank (consecutive spaces)
val splits = name.split(" ").filter { it.isNotBlank() }
// we need at least 2 strings (name and surname)
// you can also use != 2 if you want exactly 2
if (splits.size < 2) return false
// if any name is less than 3 chars, return false
for (split in splits) {
if (split.trim().length < 3) {
return false
}
}
// now we have at least 2 names and all of them have 3 or more chars
return true
}

Dynamic form with composable-form

I'm trying to implement a dynamic form in Elm 0.19 using hecrj/composable-form.
I receive a json with the fields, their descriptions, etc, so I don't know beforehand how many fields it will have.
So the traditional way of defining a form:
Form.succeed OutputValues
|> Form.append field1
|> Form.append field2
doesn't work because I don't know the OutputValues structure beforehand.
I've seen there is a function Form.list which looks like a promising path, though it seems to expect all fields equal, which is not my case, I may have a text field and a select field for example.
Is there any straight forward way of doing this with this library?
Thank you.
The form library doesn't explicitly support what you're trying to do, but we can make it work!
tldr;
Here's my example of how you can take JSON and create a form: https://ellie-app.com/bJqNh29qnsva1
How to get there
Form.list is definitely the promising path. You're also exactly right that Form.list requires all of the fields to be of the same type. So let's start there! We can make one data structure that can hold them by making a custom type. In my example, I called it DynamicFormFieldValue. We'll make a variant for each kind of field. I created ones for text, integer, and select list. Each one will need to hold the value of the field and all of the extras (like title and default value) to make it show up nicely. This will be what we decode the JSON into, what the form value is, and what the form output will be. The resulting types looks like this:
type alias TextFieldRequirements =
{ name : String
, default : Maybe String
}
type alias IntFieldRequirements =
{ name : String
, default : Maybe Int
}
type alias SelectFieldRequirements =
{ name : String
, default : Maybe String
, options : List ( String, String )
}
type DynamicFormFieldValue
= TextField String TextFieldRequirements
| IntField Int IntFieldRequirements
| SelectField String SelectFieldRequirements
To display the form, you just need a function that can take the form value and display the appropriate form widget. The form library provides Form.meta to change the form based on the value. So, we will pattern match on the custom type and return Form.textField, Form.numberField, or Form.selectField. Something like this:
dynamicFormField : Int -> Form DynamicFormFieldValue DynamicFormFieldValue
dynamicFormField fieldPosition =
Form.meta
(\field ->
case field of
TextField textValue ({ name } as requirements) ->
Form.textField
{ parser = \_ -> Ok field
, value = \_ -> textValue
, update = \value oldValue -> TextField value requirements
, error = always Nothing
, attributes =
{ label = name
, placeholder = ""
}
}
IntField intValue ({ name } as requirements) ->
Form.numberField
{ parser = \_ -> Ok field
, value = \_ -> String.fromInt intValue
, update = \value oldValue -> IntField (Maybe.withDefault intValue (String.toInt value)) requirements
, error = always Nothing
, attributes =
{ label = name
, placeholder = ""
, step = Nothing
, min = Nothing
, max = Nothing
}
}
SelectField selectValue ({ name, options } as requirements) ->
Form.selectField
{ parser = \_ -> Ok field
, value = \_ -> selectValue
, update = \value oldValue -> SelectField value requirements
, error = always Nothing
, attributes =
{ label = name
, placeholder = ""
, options = options
}
}
)
Hooking this display function up is a bit awkward with the library. Form.list wasn't designed with use-case in mind. We want the list to stay the same length and just be iterated over. To achieve this, we will remove the "add" and "delete" buttons and be forced to provide a dummy default value (which will never get used).
dynamicForm : Form (List DynamicFormFieldValue) (List DynamicFormFieldValue)
dynamicForm =
Form.list
{ default =
-- This will never get used
TextField "" { name = "", default = Nothing }
, value = \value -> value
, update = \value oldValue -> value
, attributes =
{ label = "Dynamic Field Example"
, add = Nothing
, delete = Nothing
}
}
dynamicFormField
Hopefully the ellie example demonstrates the rest and you can adapt it to your needs!

Kotlin short-cut to assign value to variable using stream function or other

for (i in 0 until result.size){ result[i].config= addConfig(taskNames!![i],processKeys!![i]) }
Here result is a list of class which has datamember config and tasNames and processKeys are list of string.
Is there a way in kotlin to map result.config with respective taskNames and processKeys without using traditional loop and mentioning length of result.I am new to kotlin.
class Process {
var processKey: String? = null
var task: List<Task>? = null}
class Task {
var taskName: String? = null
var processVariables: List<ProcessVariable>? = null}
class ProcessVariable {
var name: String? = null
var label: String? = null
var applicableValue: List<String>? = null}
Result is already present with datamember config pf type ProcessVariable
If I understand your problem correctly, you need to combine 3 lists.
So iterating over the lists may be easier to understand than some clever way of list transformations.
You can get rid of the traditional for loop, so you don't need to calculate the size of the loop:
result.forEachIndexed {
i, resultData -> resultData.config = addConfig(taskNames[i], processKeys[i])
}
If you want to combine two lists, you can use the zip method:
val configList = taskNames.zip(processKeys) {tsk, prc -> addConfig(tsk, prc)}
In your example, the result-object was already existing. Maybe it is easier to create new result-objects:
val results = configList.map {
Result(config = it)
}

How to assign a new list to a nullable field if null or else just add an element to the existing list in Kotlin?

I have an object media that holds descriptions which is a list. I'd love to see some elegant logic in Kotlin to add an element to that descriptions if the field is not null or add a fresh new list (with an initial element) to that field if it is null.
Pseudo:
if (media.descriptions == null) { media.descriptions = listOf("myValue")}
else { media.descriptions.add("myValue") }
I would probably do it the other way around, except you need to alter media itself (see below), i.e. creating your list first and add all the other entries to that list if media.descriptions isn't null:
val myDescriptions = mutableListOf("myValue") // and maybe others
media.descriptions?.forEach(myDescriptions::add)
If you need to manipulate descriptions of media, there is not so much you can do to make it more readable...:
if (media.descriptions == null) {
media.descriptions = mutableListOf("myValue") // just using mutable to make it clear
} else {
media.descriptions += "myValue"
}
or maybe:
if (media.descriptions == null) {
media.descriptions = mutableListOf<String>()
}
media.descriptions?.add("myValue")
You can use the elvis ?: operator to assign the list.
The simplest way I can think of is
media.descriptions = media.descriptions ?: listOf("myValue")
media.descriptions.add("myValue")

Creating level codes with action script 2.0

I want to create level codes, like in sea of fire (http://armorgames.com/play/351/sea-of-fire)
I have a text input box with the instance name "code" and a button that has this code:
on (release) {
if (code = 96925) {
gotoAndStop(4);
}
if (code = 34468) {
gotoAndStop(5);
}
if (code = 57575) {
gotoAndStop(6);
}
if (code = 86242) {
gotoAndStop(7);
}
if (code = 99457) {
gotoAndStop(8);
}
if (code = 66988) {
gotoAndStop(10);
}
if (code = !96925 && !34468 && !57575 && !86242 && !99457 && !66988) {
gotoAndStop(3);
}
}
I've tried to use code.text instead of just code, I've also tried quotes around the numbers, also I tried both together but it always sends you to frame 10 even if the code is invalid.
You need to use conditional operator (==), not equality operator (=) in 'if' condition
Also if 'code' is a text field then you need to use code.text
You can put trace to check for the value of code.
I do not understand your last if condition
Instead you can use if - else if - else here.