If I just want to determine a value is present, which Swift data structure should I use? - dictionary

I'm looking at a bunch of names, and I want to record all the names. My plan was to iterate over the array of names, and use a dictionary to keep track of each name, so I could just look up the name in the dictionary in O(1) time to see if it existed.
What would be the best data structure for this available in Swift? (I'd love to learn the name of the generic data structure that would be best for this, even if it's not in Swift.)
A Dictionary object would do fine, but it requires a value for the key, when I really only need the key.

You're looking for a Set (a collection of unordered unique objects - some implementations are ordered, though).
Swift and ObjectiveC have NSSet, wouldn't this work for you?

Swift does not provide a set type. You can refer to this blog post for how to define a Set.
Code reproduced here for quick reference:
struct Set<T: Hashable> {
typealias Element = T
private var contents: [Element: Bool]
init() {
self.contents = [Element: Bool]()
}
/// The number of elements in the Set.
var count: Int { return contents.count }
/// Returns `true` if the Set is empty.
var isEmpty: Bool { return contents.isEmpty }
/// The elements of the Set as an array.
var elements: [Element] { return Array(self.contents.keys) }
/// Returns `true` if the Set contains `element`.
func contains(element: Element) -> Bool {
return contents[element] ?? false
}
/// Add `newElements` to the Set.
mutating func add(newElements: Element...) {
newElements.map { self.contents[$0] = true }
}
/// Remove `element` from the Set.
mutating func remove(element: Element) -> Element? {
return contents.removeValueForKey(element) != nil ? element : nil
}
}
Otherwise, you can just use Dictionary and use the name as both key and value.

Related

TypeScript Checker Symbol Of "this"

I have this ts.Program/ts.SourceFile:
class MyClass {
foo() {
// #1
}
}
Is there a way to obtain the symbol/type of the local this value at position #1?
Unfortunately, this is not listed by checker.getSymbolsInScope.
Ideally I would get the type of MyClass, so I could explore its members.
The solution should also work for these cases:
function foo(this: MyClass) {
// #2
}
const obj = {
bar() {
// #3
}
};
Thank you!
edit: This is the feature I needed this for:
There is an internal TypeChecker#tryGetThisTypeAt(nodeIn: ts.Node, includeGlobalThis = true): ts.Type method that will return this information. If you're ok with using internal API, then you can do:
const type = (checker as any).tryGetThisTypeAt(nodeName) as ts.Type;
To get the node's name, you'll need to traverse the tree to find the method or function declaration that is contained within the position, then the .name property will contain the node that you can provide to tryGetThisTypeAt.

Return value from map.forEach in dart?

I want to search for a value in a Map.
Map<String, dynamic> map;
dynamic someThing;
map.forEach((String key, dynamic value) {
if (value == someThing) {
return value;
}
});
but I get this warning:
Don't assign to void.dart(void_checks)
how can I do it without getting this warning?
The reason why you get the warning is because the return statement is inside the submethod you have defined as an argument to the forEach method. But since this method has the signature of void f(K key, V value), you will get a warning when you try returning some value.
So you can make it like this instead so you don't define a new submethod:
Map<String, dynamic> map;
dynamic someThing;
for (final value in map.values) {
if (value == someThing) {
return value;
}
}
There are 2 types of for-each in dart - the map.forEach is used to go through every element, and return something based on it (like turning an array of strings into a Cell for display).
What you want is a more regular for (Value value in values), where you get more freedom what to do, and can return at any point :)
I think when I tried map.forEach wrongly last time I also got a different warning telling me also not to use it O.O

How to transform a Custom Object List by excluding particular property in Kotlin?

How to transform a List into a new List by excluding a property in T.
For instance if User data class has 10 properties, I need to transform List into a new List without one particular property in User . New List like List
data class User(val name: String, val age: Int)
var userList = mutableListOf<User>()
var nameList= userList.map { it.name }
If a List to be created without property 'age'. Like
var withoutAgeList
In your first example:
var userList = mutableListOf<User>()
var nameList= userList.map { it.name }
The question "What's the type of nameList?" has a simple answer: List<String>. So let me ask you a similar question: What's the type of withoutAgeList? The answer to that question informs the answer to your question.
Perhaps a user without the age property is a separate AgelessUser class, meaning withoutAgeList is of type List<AgelessUser>. In that case, I suggest either a constructor or a factory function that builds AgelessUser from User, and you want one of these:
val withoutAgeList = userList.map { AgelessUser(it) } // constructor
val withoutAgeList = userList.map { agelessUserOf(it) } // factory
Alternatively, maybe the age property in User is nullable and immutable, and you want to represent users without an age as a regular User where age=null. In this case, you could copy the Users and override the age field
// TODO: pass all the other fields too
val withoutAgeList = userList.map { User(it.name, null) }
Assuming Users is a data class, we can avoid explicitly naming all fields by making use of copy():
val withoutAgeList = userList.map { it.copy(age = null) }
Maybe the age property is nullable and mutable — and you actually want to change the users in place instead of copying them. This is somewhat risky and I don't advocate doing it this way unless you really know what you're doing though.
userList.forEach { it.age = null }
// They're actually the same list!
val withoutAgeList = userList
In such a simple case you can map a list of Users into a list of strings:
val names: List<String> = userList.map(User::name)
Or you can declare a DTO and map into the latter:
class UserWithoutAge(val name: String)
val usersWithoutAge: List<UserWithoutAge> = userList.map { UserWithoutAge(it.name) }
P.S. you don't have to write an explicit type
You can use the Object Oriented approach:
data class User(val name: String, val age: Int)
data class UserNoAge(var name: String) {
constructor(user: User) : this(user.name)
}
var userList = listOf(User("John", 25), User("Jane", 30))
var userNoAge: List<UserNoAge> = mutableListOf<UserNoAge>()
userNoAge = userList.map{ UserNoAge(it) }
println(userNoAge) // [UserNoAge(name=John), UserNoAge(name=Jane)]

JSON Lists not removing duplicates with Distinct command

Currently I am querying a web service that returns a JSON string.
url = #"redacted url;
returnValue = new WebClient().DownloadString(url);
I am putting the return results into a list of items defined in a model class. I am then running a second JSON call searching a different field with that same search term.
url2 = #"redacted url2;
returnValue2 = new WebClient().DownloadString(url2);
I then create my lists and combine the lists using AddRange.
List<Order> shipments = JsonConvert.DeserializeObject<List<Order>>(returnValue);
List<Order> shipments2 = JsonConvert.DeserializeObject<List<Order>>(returnValue2);
shipments.AddRange(shipments2);
As a result there are some duplicates. To try and only return unique records I am using the command Distinct when sending to my MVC view from the controller.
return View(shipments.OrderBy(x => x.dtDateReceived).Distinct().ToList());
But for some reason it's still returning duplicates.
Any ideas on what I am doing wrong here?
Thanks in advance for any help!
I ended up correcting it using Shyju's comment above.
I changed the Distinct to the following.
return View(shipments.OrderBy(x => x.dtDateReceived).Distinct(new OrderComparer()).ToList());
Then built the following compare functions
// Custom comparer for the Order class
class OrderComparer : IEqualityComparer<Order>
{
// Orders are equal if their names and order numbers are equal.
public bool Equals(Order x, Order y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the order's properties are equal.
return x.sWorkOrderNumber == y.sWorkOrderNumber && x.sCustomerOrderName == y.sCustomerOrderName;
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(Order order)
{
//Check whether the object is null
if (Object.ReferenceEquals(order, null)) return 0;
//Get hash code for the sCustomerOrderName field if it is not null.
int hashOrderName = order.sCustomerOrderName == null ? 0 : order.sCustomerOrderName.GetHashCode();
//Get hash code for the sWorkOrderNumber field.
int hashOrderCode = order.sWorkOrderNumber.GetHashCode();
//Calculate the hash code for the order.
return hashOrderName ^ hashOrderCode;
}
}

Flex looping through object

Im trying to extend the flex ArrayCollection to be able to search for an object containing specific data and give it back.
Here is my function:
public function getItemContaining(value: String): Object {
//Loop through the collection
for each(var i: Object in this) {
//Loop through fields
for(var j: String in i) {
//If field value is equal to input value
if(i[j] == value) {
return i;
}
}
}
//If not found
return null;
}
Problem is j is always null so the second loop never works. So I read flex loop descriptions and actually it should work just fine. What can possibly be the problem?
Try it like this:
for (var name:String in myObject){
trace(name + ":" + myObject[name];
}
Okay that was actually the same you were doing. The error must be in this line:
for each(var i: Object in this) {
Try using this:
for each(var i: Object in this.source) {
My first instinct would be to have a look at data type. You're setting up a loop declaring j:String and the symptom is that j is always null. This suggests to me that Flex is failing to interpret the elements of i as strings. If Flex only recognizes the elements of i as Objects (because all Strings are Objects, and Objects are the lowest common denominator), it would return null for j:String.
Try this for your inner loop:
for(var j: Object in i) {
//If field value is equal to input value
if(i[j] is String && (i[j] as String) == value) {
return i;
}
}
if you are using ArrayCollection as your datasource, you should look at using the IViewCursor interface. You can supply a custom compare function, or supply the fields top compare to. This interface is well documented with examples in adobe/livedocs
var _cursor:IViewCursor;
var _idSortField:SortField;
var _idSort:Sort = new Sort();
_idSortField = new SortField();
_idSortField.compareFunction = this.myCompareFunction;
_idSort.fields = [_idSortField];
myArrayCollection.sort = _idSort;
myArrayCollection.refresh();
_cursor = myArrayCollection.createCursor();
if (_cursor.findAny(search))
return _cursor;
if you are search for a value in a specific property, then its even easier. Here's the link to adobe livedocs on this topic

Resources