Im learning swift 3 and I have a question here
Sorry for wrong example..couldnt think of logical example
enum Restaurant : String {
case wendys = "wendy's"
case chickfila = "chick fil'a"
case subway = "SubWay"
}
public struct COMMON_INFO {
var restaurant : Restaurant?
public static let restaurant_zip: String?
init(restaurant: Restaurant) {
switch restaurant {
case .wendys: break
COMMON_INFO.restaurant_zip = "212345"
self.restaurant = restaurant
case .chickfila: break
COMMON_INFO.restaurant_zip = "367849"
self.restaurant = restaurant
default: COMMON_INFO.restaurant_zip = "618374"
self.restaurant = restaurant
break
}
}
public static func getAddressFromZip() -> [String : Any] {
let address = getAddressFrom(restaurant_zip)
//do something with address
}
func getAddressFrom(zip:String) {
//get address
}
}
Code Snippet
I have an enum defined
I have a constant "restaurant_zip" defined in structure COMMON_INFO
I need to set the value of restaurant_zip depending on the value of variable restaurant
For that reason, i added an initializer and assigning value of static variable depending on case like shown in code
but i get error on line "public static let restaurant_zip: String?" -> "static var declaration requires an initializer expression"
my requirement is to have a static function getAddressFromZip in which i use static variable restaurant_zip" whose value is to be defined from initializer of struc COMMON_INFO
Please help me how to acheive this . Ive been trying but no luck
Not sure if I get what you want, but using var instead might help:
public static var restaurant_zip: String?
Related
I have created a TextFormField in flutter. I have a class named ParticipantsData with a few properties listed. I can access and store values in all of those properties by making an object of ParticipantsData class in another class named "RegistrationForm". However I am unable to store data in the properties that are of type List even after having initialized them.
I have tried:
- List.filled()
- =[]
- =[""]
- List.generate()
- List()
- List<String>()
- List<String>(length)
I have changed my code multiple times over and tried many methods but nothing seems to work. I don't post here much because I usually find solutions on stackoverflow but this time I couldn't find anything.
Unable to post the whole code because it is too long. Below is the relevant code:
ParticipantsData class:
class ParticipantsData {
List name = []; //members
bool paymentstatus = false; //payment
String email = ""; //email
String address = ""; //address
List contact = []; //contact
String collegename = ""; //collegename
String password = ""; //password
String teamname = ""; //teamname
var modules = List<String>(6); //modules
ParticipantsData({
this.name,
this.email,
this.contact,
this.collegename,
this.address,
this.modules,
this.password,
this.paymentstatus,
this.teamname,
});
}
Below is the relevant code for Register class:
class _RegistrationForm extends State<RegistrationForm> {
final ParticipantsData data = new ParticipantsData();
//This is the onSaved method of a TextFormField, which is in a loop.
(String value) { //Tried this...
data.name[i + 1] = value;
print('${data.name[i + 1]}');
}),
(String value) { //And this too...
data.name.add(value);
print('${data.name[i + 1]}');
}),
The assigned values become null when initialized inside the constructor. If you don't include the fields in the constructor, they will not reset to null.
However, you may want to assign the values in the constructor and want some default value if the field is not provided while creating the instance. Here is how to do so:
class MyClass {
// Don't initialize here
List x;
int y;
MyClass({
this.x,
this.y = 10, // If y is not assigned, it will take a default value of 10
}) {
// Constructor body
this.x = this.x ?? []; // If x is not assigned, it will take a value of []
}
}
Notice that y can be provided with the default value directly as 10 is a constant value. You can only assign constant default values in the constructor parameter list. Since [ ] is not a constant expression or value, it can't be directly assigned as the default value hence, you need to define the constructor body assigning x = [ ] if x is null.
this.x = this.x ?? [];
You can initialize the others in a similar way.
I'm trying to add an element list to the list of string, but I found Kotlin does not have an add function like java so please help me out how to add the items to the list.
class RetrofitKotlin : AppCompatActivity() {
var listofVechile:List<Message>?=null
var listofVechileName:List<String>?=null
var listview:ListView?=null
var progressBar:ProgressBar?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_retrofit_kotlin)
listview=findViewById<ListView>(R.id.mlist)
var apiInterfacee=ApiClass.client.create(ApiInterfacee::class.java)
val call=apiInterfacee.getTaxiType()
call.enqueue(object : Callback<TaxiTypeResponse> {
override fun onResponse(call: Call<TaxiTypeResponse>, response: Response<TaxiTypeResponse>) {
listofVechile=response.body()?.message!!
println("Sixze is here listofVechile ${listofVechile!!.size}")
if (listofVechile!=null) {
for (i in 0..listofVechile!!.size-1) {
//how to add the name only listofVechileName list
}
}
//println("Sixze is here ${listofVechileName!!.size}")
val arrayadapter=ArrayAdapter<String>(this#RetrofitKotlin,android.R.layout.simple_expandable_list_item_1,listofVechileName)
listview!!.adapter=arrayadapter
}
override fun onFailure(call: Call<TaxiTypeResponse>, t: Throwable) {
}
})
}
}
A more idiomatic approach would be to use MutableList instead of specifically ArrayList. You can declare:
val listOfVehicleNames: MutableList<String> = mutableListOf()
And add to it that way. Alternatively, you may wish to prefer immutability, and declare it as:
var listOfVehicleNames: List<String> = emptyList()
And in your completion block, simply reassign it:
listOfVehicleNames = response.body()?.message()?.orEmpty()
.map { it.name() /* assumes name() function exists */ }
Talking about an idiomatic approach... 🙄
When you can get away with only using immutable lists (which means usually in Kotlin), simply use + or plus. It returns a new list
with all elements of the original list plus the newly added one:
val original = listOf("orange", "apple")
val modified = original + "lemon" // [orange, apple, lemon]
original.plus("lemon") yields the same result as original + "lemon". Slightly more verbose but might come in handy when combining several collection operations:
return getFruit()
.plus("lemon")
.distinct()
Besides adding a single element, you can use plus to concatenate a whole collection too:
val original = listOf("orange", "apple")
val other = listOf("banana", "strawberry")
val newList = original + other // [orange, apple, banana, strawberry]
Disclaimer: this doesn't directly answer OP's question, but I feel that in a question titled "How to add an item to a list in Kotlin?", which is a top Google hit for this topic, plus must be mentioned.
If you don't want or can't use array list directly use this code for add item
itemsList.toMutableList().add(item)
itemlist : list of your items
item : item you want to add
instead of using a regular list which is immutable just use an arrayListof which is mutable
so your regular list will become
var listofVehicleNames = arrayListOf("list items here")
then you can use the add function
listOfVehicleNames.add("what you want to add")
you should use a MutableList like ArrayList
var listofVechileName:List<String>?=null
becomes
var listofVechileName:ArrayList<String>?=null
and with that you can use the method add
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/add.html
For any specific class, the following may help
var newSearchData = List<FIRListValuesFromServer>()
for (i in 0 until this.singleton.firListFromServer.size) {
if (searchText.equals(this.singleton.firListFromServer.get(i).FIR_SRNO)) {
newSearchData.toMutableList().add(this.singleton.firListFromServer.get(i))
}
}
val listofVechile = mutableListOf<String>()
Declare mutable list like that and you will be able to add elements to list :
listofVechile.add("car")
https://kotlinlang.org/docs/collections-overview.html
I want to create a list in flutter that contains variable. Now when I am trying to edit the contents of the list, it actually gets stored in the list itself. For eg.,
static var _ratingSelected = "";
static var _disconnectSelected = "";
static var _uTypeSelected = "";
List finalSelectedList = [_uTypeSelected,_disconnectSelected,_ratingSelected];
This is my list, when I will edit the list, like,
finalSelectedList[0] = "Main";
The output list will be like
finalSelectedList = ["Main",_disconnectSelected,_ratingSelected];
It will edit the finalSelectedList[0] position of the list but not the variable _uTypeSelected. Is there any way so that the value gets stored in the variable _uTypeSelected and not at the position finalSelectedList[0]?
There is no way to do that. If you use finalSelectedList[0].someProp = "Main"; where the variables are instances of some classes that have a someProp property, then it would work, because there is an additional abstraction. Strings are primitive values and copied by value when added to a list and therefore there is no connection left between list entry and variable.
class Foo {
Foo(this.someProp);
String someProp;
}
static var _ratingSelected = Foo("");
static var _disconnectSelected = Foo("");
static var _uTypeSelected = Foo("");
List finalSelectedList = [_uTypeSelected,_disconnectSelected,_ratingSelected];
finalSelectedList[0].someProp = "Main";
I am currently having a list of obeject defined as:
fun updateList(tools: List<Tool>, updateTools: List<Updated>){
... code below
}
the Tool data class is defined as:
data class Tool(
var id: String = ""
var description: String = ""
var assignedTo: String = ""
)
the Updated data class is defined as:
data class Updated(
var id: String = ""
var assignedTo: String = ""
)
Basically, I parse the list updateTools and if I found a id match in tools, I update the assignedTo field from the Tool type object from tools by the one from updateTools
fun updateList(tools: List<Tool>, updateTools: List<Updated>){
updateTools.forEach{
val idToSearch = it.id
val nameToReplace = it.name
tools.find(){
if(it.id == idToSearch){it.name=nameToReplace}
}
}
return tools
}
it's not working but I do not see how to make it easier to work. I just started kotlin and I feel that it's not the good way to do it
any idea ?
Thanks
First of all:
you're not assigning assignedTo, you're assigning name...
in the predicate passed to find, which
should only return a Boolean value to filter elements, and
should probably not have any side effects,
those should be done later with a call to i.e. forEach.
Additionally, your constructor parameters to the data class are normal parameters, and as such, need commas between them!
Your last code block, corrected, would be:
updateTools.forEach {
val idToSearch = it.id
val nameToReplace = it.name
tools.find { it.id == idToSearch }.forEach { it.assignedTo = nameToReplace }
}
return tools
I'd do it like this (shorter):
updateTools.forEach { u -> tools.filter { it.id == u.id }.forEach { it.assignedTo = u.name } }
This loops through each update, filters tools for tools with the right ID, and sets the name of each of these tools.
I use forEach as filter returns a List<Tool>.
If you can guarantee that id is unique, you can do it like this instead:
updateTools.forEach { u -> tools.find { it.id == u.id }?.assignedTo = u.name }
firstOrNull returns the first element matching the condition, or null if there is none. Edit: it seems find is firstOrNull - its implementation just calls firstOrNull.
The ?. safe call operator returns null if the left operand is null, otherwise, it calls the method.
For = and other operators which return Unit (i.e. void, nothing), using the safe call operator simply does nothing if the left operand is null.
If we combine these, it effectively sets the name of the first element which matches this condition.
First, you're missing comma after properties in your data classes, so it should be:
data class Tool(
var id: String = "",
var description: String = "",
var assignedTo: String = ""
)
data class Updated(
var id: String = "",
var assignedTo: String = ""
)
As for second problem, there're probably number of ways to do that, but I've only corrected your idea:
fun updateList(tools: List<Tool>, updateTools: List<Updated>): List<Tool> {
updateTools.forEach{ ut ->
tools.find { it.id == ut.id }?.assignedTo = ut.assignedTo
}
return tools
}
Instead of assigning values to variables, you can name parameter for forEach and use it in rest of the loop.
I have absolutely no knowledge in Regex whatsoever. Basically what I'm trying to do is have an error class that I can use to call errors (obviously) which looks like this:
package avian.framework.errors
{
public class AvError extends Object
{
// errors
public static const LAYER_WARNING:String = "Warning: {0} is not a valid layer - the default layer _fallback_ has been used as the container for {1}.";
/**
* Constructor
* Places a warning or error into the output console to assist with misuse of the framework
* #param err The error to display
* #param params A list of Objects to use throughout the error message
*/
public function AvError(err:String, ...params)
{
trace(err);
}
}
}
What I want to be able to do is use the LAYER_WARNING like this:
new AvError(AvError.LAYER_WARNING, targetLayer, this);
And have the output be something along the lines of:
Warning: randomLayer is not a valid layer - the default layer _fallback_ has been used as the container for [object AvChild].
The idea is to replace {0} with the first parameter parsed in ...params, {1} with the second, etc.
I've done a bit of research and I think I've worked out that I need to search using this pattern:
var pattern:RegExp = /{\d}/;
You can use StringUtil
var original:String = "Here is my {0} and my {1}!";
var myStr:String = StringUtil.substitute(original, ['first', 'second']);
Using the g flag in RegExp you can create an array containing all of your {x} matches, then loop through this array and replace each of the matches with the appropriate parameter.
Code:
var mystring:String = "{0} went to {1} on {2}";
function replace(str:String, ...params):String
{
var pattern:RegExp = /{\d}/g;
var ar:Array = str.match(pattern);
var i:uint = 0;
for(i; i<ar.length; i++)
{
str = str.split(ar[i]).join(params[i]);
}
return str;
}
trace(replace(mystring, "marty", "work", "friday")); // marty went to work on friday
i'm assuming you want to have several static constants with varying replacement instances ({0}, {1}, {2}, etc.) in each string constant.
something like this should work - sorry, it's untested:
public function AvError(err:String, ...params)
{
var replacementArray:Array = err.match(new RegExp("{\\d}", "g"));
for (var i:int = 0, i < replacementArray.length, i++)
err = err.replace(new RegExp(replacementArray[i], "g"), params[i]);
trace(err);
}
if you do have several static constants with varying replacement instances, you'll want to check for an appropriate matching amount of …params that are passed.