I am a beginner of Kotlin. I would like to initial an empty custom class array. Most Kotlin tutorials focus on primitive types Array, but not custom class Array.
I have tried the following, but it failed to work.
class MyAudioPlayer {
// Error
// Type mismatch: inferred type is Unit but AudioItem was expected.
var items: Array<AudioItem> = Array<AudioItem>(0) {}
......
}
Any suggestions? Thanks
The Array constructor you're using takes a size and a lambda that creates an element for each index, for example you could use it like this (pretending that AudioItem takes an Int parameter):
var items: Array<AudioItem> = Array<AudioItem>(0) { index -> AudioItem(index) }
But to create an empty Array, you can just use arrayOf:
var items: Array<AudioItem> = arrayOf()
Or simply emptyArray:
var items: Array<AudioItem> = emptyArray()
If you want to initialize by different known objects
var myData = arrayOf(
AudioItem("Tartak", "Song 1", 3.52),
AudioItem("Topolsky", "Song 2", 5.7)
)
The simplest way with an initial size of 0 is with emptyArray:
var items = emptyArray<AudioItem>()
Related
I have two differents arrays with those models
export interface ProfileMaterialCategory{
id?: string
materialCategory_Name?: string
materialCategory_Id: string
quantity: string
profileId?: string
}
And
import { Category } from "./material-asset-model";
export interface UserAssetsCount {
category: Category
userAssetsCount: number;
}
In my .ts file I'm trying to create a method for getting a combined records for all matching materialCategory_Id / category.Id.
The returned array must have this syntax
[category.name:string, userAssetsCount:string, quantity:string]
I tried with filter and includes but it his not working, or I don't take the problem correctly.
This is the arguments that the method takes.
GetMatch(profileAssets: ProfileMaterialCategory[], userAssets: UserAssetsCount[]): Object[] {
var filteredArray = userAssetsAllowed.filter(
as
setAllowed => userAssetsCount.some(
assetCount => assetCount.category.id.toString() == assetAllowed.materialCategory_Id)
return filteredArray
}
When I filter, I receive an element of the array when the condition is true, but it's an element from one of the array, I can't take value from the other.
So, I've succed in one way to do what I needed.
First I created a new DTO model:
export interface UserAssetMatch {
category: Category,
allowed: string,
owned: number
}
Then I make a foreach() loop on one array, and use a filter() on the second array. I keep the matching elements in an intermediate array.
If there is something in the intermediate array, I push the informations that I need in the DTO.
GetMatch(userAssetsAllowed: ProfileMaterialCategory[], userAssetsCount: UserAssetsCount[]): UserAssetMatch[] {
var matchArray: UserAssetMatch[] = [];
userAssetsCount.forEach(userAsset => {
var profileAssets = userAssetsAllowed.filter(userAssetAllowed => userAsset.category.id.toString() == userAssetAllowed.materialCategory_Id);
if (profileAssets.length > 0) {
matchArray.push({
category: userAsset.category,
owned: userAsset.userAssetsCount,
allowed: profileAssets[0].quantity
})
}
});
return matchArray;
I don't think it is a good way to do, but it works. If someone have a better/faster/cleaner way to do, please tell me :)
This is the obj array
workflows: ProteusWorkflow[]
ProteusWorkflow obj looks like this
export class ProteusWorkflow{
id: number;
workflowName :string
}
I need to add all the workflowNames from above Array to
filteredWorkflowsNew$: Observable<string[]>;
How can I do this? Please help me out!!
I've tried this...
this.workflows.forEach(w => {
this.filteredWorkflowsNew$.pipe(map(wfs=>{
wfs.push(w.workflowName);
return this.filteredWorkflowsNew$;
}));
});
but didn't work.
You can use the Array.prototype.map() operator.
map() function creates a new array populated with the results of
calling a provided function on every element in the calling array.
Please find more details about use of Array.prototype.map()
here.
let workflows = [{id:1,workflowName:"ABC"},{id:1,workflowName:"BDF"},{id:1,workflowName:"EWQ"}];
let filteredWorkflowsNew$=[];
filteredWorkflowsNew$ = workflows.map(obj => obj.workflowName);
console.log(filteredWorkflowsNew$) // ["ABC","BDF","EWQ"]
I'm trying to create an array of two items: a URL and a String. The index of the items is of significance.
The data is taken from QuartzFilterManager, which provides information about the Quartz Filters installed on a system.
import Cocoa
import Quartz
class myFilter {
var myURL: URL?
var name: String = ""
}
func getFilters() -> Array<String> {
var filterArray: Array<myFilter>
if let Filters = QuartzFilterManager.filters(inDomains: nil) {
for (index, eachFilter) in Filters.enumerated() {
filterArray[index].name.append((eachFilter as! QuartzFilter).localizedName()!)
filterArray[index].myURL!.append((eachFilter as! QuartzFilter).url()!)
}
}
}
Xcode complains about Type URL not having an append method. But the name property in the preceding line works. In short, how do I set specific properties in my array?
There are lots of issues.
Make myFilter a struct instead of class and name it properly as MyFilter.
You never initialize your filterArray, you only declare it.
You need to create a new instance of MyFilter for each url/name pair you want to add to the array.
You don't need to use enumerated in this case.
You have the wrong return type for your getFilter function (I think).
Use proper naming conventions.
Here's cleaned up code:
struct MyFilter {
var myURL: URL?
var name: String
}
func getFilters() -> [MyFilter] {
var filterArray = [MyFilter]()
if let filters = QuartzFilterManager.filters(inDomains: nil) {
for eachFilter in filters {
let filter = MyFilter(myURL: (eachFilter as! QuartzFilter).url(), name: (eachFilter as! QuartzFilter).localizedName()!)
filterArray.append(filter)
}
}
return filterArray
}
It's still not ideal. Having to cast eachFilter using as! QuartzFilter is clunky.
And other uses of ! are bad. Force-unwrapping the call to localizedName() can crash. Consider proper solutions.
Append is a method of the array struct, not of the URL/String.
You first need to create the array (you just declared it, you actually need to assign something to it)
You then need to create the object that you want to append into the array
You can now append this newly created object to the array
It should look something like this:
import Cocoa
import Quartz
class MyFilter {
var myURL: URL?
var name: String?
init(url: URL?, name: String?) {
self.myURL = url
self.name = name
}
}
func getFilters() -> Array<MyFilter> {
var filterArray = [MyFilter]()
if let filters = QuartzFilterManager.filters(inDomains: nil) {
for filter in filters {
let aFilter = MyFilter(url: filter.url(), name: filter.localizedName())
filterArray.append(aFilter)
}
}
return filterArray
}
Now the array returned by this method will have N MyFilter objects.
You can access every object in the array the way you did before, with
let aFilter = filterArray[index]
And to get the property inside of that object:
let url = aFilter.myURL
let name = aFilter.name
PS: I changed some names to fit the swift conventions (classes are written in PascalCase and variables in camelCase)
PpS: be careful with ! in swift, if it's used on something that happens to be nil will crash the app. Read more about optionals here
PpPs: I was just a few minutes late :D
I have a Json string which contains many json objects, each json has a key, I use JSON.parse to place the string into an object.
I then extract what I need in the following format
json['product1'][0].name
However, I want to get an array of element from each of the json objects based on the value of another elements. Currently I am using:
for each (var row:Object in json) {
if (row[0][filterElement] == filterValue) {
arr.push(row[0][element]);
}
}
Is this a good approach? I ask because it seems that I am going through the entire json object every time.
If I've understood your question correctly, it sounds like you want to use .map and .filter.
So if we have an object such as...
var obj = {
people: [
{name: 'person1'},
{name: 'person2'},
{name: 'person3'},
{name: 'person4'},
]
};
You can then use .map to create a new array of names...
var names = obj.people.map(function(person){
return person.name;
}); // ['person1', 'person2', 'person3', 'person4']
on this array you can then use .filter...
var filter = 'person2';
var filteredNames = obj.people.map(function(person){
return person.name;
}).filter(function(name){
return name == filter; // if true, will push name into a name into our new array
}); // 'person2'
This is obviously a rudimentary example, but the same concepts will apply for the precise properties which apply in your question. Hope this helps.
It drives me crazy. I have a really simple "problem" and it took me hours and still have no idea whats going on.
I have a child service which inherits from a parent service (I'm using ES6). The constructor takes an 1 argument called options. options will be assigned to this._defaults.
Now before I pass the options into my object (new Service(options)) I populate options with some data. To keep it simple, my current options object looks like this:
const options = {
types: []
}
Now I add some stuff into the types array, like this:
const Types = {
standard: {
some: 'data'
},
freeroll: {
some: 'data'
},
mainevent: {
some: 'data'
},
qualifier: {
some: 'data'
}
};
angular.forEach(Types, (val, key) => {
options.types[key] = true;
});
I assign my service to the scope like this:
$scope.service = new Service(options)
and output the service using console. The console now says the value of _defaults.types is Array(0). When I click on the array the correct values will be shown but the scope is not aware of that.
How is that? Doesn't Array(0) mean that at the time of the console.log() the array wasn't filled with any values but has been later? Like an async function would do?
Here is a plunk of my problem.
The problem is that types is an array and you're treating it like a plain Object. You can solve this one of two ways.
First just change types to an Object:
const options = {
types: {}
};
Or, if you need an Array, change how you're adding items to the array:
angular.forEach(Types, (val, key) => {
options.types.push({
type: key,
value: val
});
});
Note that this is just one way of turning the object into an array, the data structure you end up with is up to you.