I know that Filter and contains in Swift are very powerful and it has made many of my works easy. However, I'm stranded in a situation where I have to filter/verify a set of different values from an array of Model.
Let's assume I have a model like below
struct Person {
var name: String
var ID: String
}
And I have an array of models like below:
[
{
sku = "123"
attributes = [
{
name:"Victor"
ID:"250"
},
{
name:"Shaw"
ID:"252"
}
]
},
{
sku = "123"
attributes = [
{
name:"John"
ID:"222"
},
{
name:"Nixon"
ID:"333"
}
]
}
]
Now I would like to filter the sku by multiple IDs inside attributes . For example, if I need to filter skus which has ID:250 and ID:252 I need something like this to achieve it.
personModelArray.forEach { person in
person.attributes.contains(where: { $0.ID == 250 && $0.ID == 252 })
}
OR
personModelArray.forEach { person in
person.attributes.filter { $0.ID == 250 && $0.ID == 252 }
}
What I want is a condition like to to verify that the attributes array has both the values.
The condition $0.ID == 250 && $0.ID == 252 is ALWAYS false! How one storage could have two different values at the same moment?
Look at this simple example
struct Item {
let a: Int
let b: String
}
let arr = [Item(a: 0, b: "zero"),
Item(a: 1, b: "one"),
Item(a: 2, b: "two"),
Item(a: 4, b: "four")]
To filter all items, where a == 1 OR a == 4
let arr0 = arr.filter { item in
item.a == 1 ||
item.a == 4
}
or, if You prefer $ parameter notation
let arr1 = arr.filter { $0.a == 1 || $0.a == 4 }
eventually,
let arr2 = arr.filter { item in
[1, 4].contains(item.a)
}
let arr3 = arr.filter { [1, 4].contains($0.a) }
Consider I have a variable -
[
{
"outer_key_1" = [
{
"ip_cidr" = "172.16.6.0/24"
"range_name" = "range1"
},
{
"ip_cidr" = "172.16.7.0/24"
"range_name" = "range2"
},
{
"ip_cidr" = "172.17.6.0/24"
"range_name" = "range3"
},
{
"ip_cidr" = "172.17.7.0/24"
"range_name" = "range4"
},
]
},
{
"outer_key_2" = [
{
"ip_cidr" = "172.16.5.0/24"
"range_name" = "range5"
},
{
"ip_cidr" = "172.17.5.0/24"
"range_name" = "range6"
},
]
},
]
I am able to merge the maps inside the list to get this output -
{
"outer_key_1" = [
{
"ip_cidr" = "172.16.6.0/24"
"range_name" = "range1"
},
{
"ip_cidr" = "172.16.7.0/24"
"range_name" = "range2"
},
{
"ip_cidr" = "172.17.6.0/24"
"range_name" = "range3"
},
{
"ip_cidr" = "172.17.7.0/24"
"range_name" = "range4"
},
]
"outer_key_2" = [
{
"ip_cidr" = "172.16.5.0/24"
"range_name" = "range5"
},
{
"ip_cidr" = "172.17.5.0/24"
"range_name" = "range6"
},
]
}
I have done this using
result = merge(variable[0], variable[1])
But when I try this
result = merge(variable[*])
I get an error saying
Call to function "merge" failed: arguments must be maps or objects, got
"tuple".
Why does merge fail when I use the splat operator?
Is there a better way to merge maps in list as required above?
The merge function is defined to take one or more separate arguments that are each map or object values. When you call merge(variable) (which is the same as merge(variable[*]) if variable is already a list) you're instead giving it one list argument, leading to this error.
To pass the elements of a list or tuple as multiple individual arguments, you can use argument expansion syntax:
result = merge(variable...)
The ... symbol, when given after the last argument in a function call, tells Terraform to evaluate the expression as a list or tuple before calling the function, and then use the elements in that result a separate argument each.
In other words, merge(variable...) is the same as merge(variable[0], variable[1], variable[2]) etc for each element in the list, without needing to know ahead of time how many elements are in the list.
Applying the splat operator [*] to a value that is already a list is redundant; the splat operator is useful in this situation only when it's followed by at least one additional attribute name or index, like example[*].id or example[*][0].
There is one situation where a lonely [*] with no following steps can be useful: if you apply it to anything that isn't a list or tuple then Terraform will either wrap it in a single-element list (if it's non-null) or return an empty list (if it's null), which can be useful in some unusual cases where you're given a single value that might be null and need to adapt it into a zero-or-one length list to use with features like resource for_each and in dynamic blocks.
I am pulling data from Firebase and in every loop I will get one piece of data in NSDictionary format (e.g. 1st loop I get {Kelvin: 10} , 2nd loop I get {John, 40}, 3rd loop I get {Mary, 27} ,etc)
I created a variable called "namedic" to store the data
var namedic = [NSDictionary]()
I then use an if statement in the loop to catch the data
if let myname = thename["name:"] as? NSDictionary {
//(thename["name:"] prints {Kelvin: 10}
self.namedic.append(myname)
}
I will then get an array of NSDictionaries
[{
"Kelvin" = 10;
}, {
"John" = 40;
}, {
"Mary" = 27;
}]
My question is, how do I sort this array of NSDictionaries in alphabetical order?
What I want is this:
[{
"John" = 40;
}, {
"Kelvin" = 10;
}, {
"Mary" = 27;
}]
Say I have a TypeScript enum, MyEnum, as follows:
enum MyEnum {
First,
Second,
Third
}
What would be the best way in TypeScript 0.9.5 to produce an array of the enum values? Example:
var choices: MyEnum[]; // or Array<MyEnum>
choices = MyEnum.GetValues(); // plans for this?
choices = EnumEx.GetValues(MyEnum); // or, how to roll my own?
This is the JavaScript output of that enum:
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["First"] = 0] = "First";
MyEnum[MyEnum["Second"] = 1] = "Second";
MyEnum[MyEnum["Third"] = 2] = "Third";
})(MyEnum || (MyEnum = {}));
Which is an object like this:
{
"0": "First",
"1": "Second",
"2": "Third",
"First": 0,
"Second": 1,
"Third": 2
}
Enum Members with String Values
TypeScript 2.4 added the ability for enums to possibly have string enum member values. So it's possible to end up with an enum that look like the following:
enum MyEnum {
First = "First",
Second = 2,
Other = "Second"
}
// compiles to
var MyEnum;
(function (MyEnum) {
MyEnum["First"] = "First";
MyEnum[MyEnum["Second"] = 2] = "Second";
MyEnum["Other"] = "Second";
})(MyEnum || (MyEnum = {}));
Getting Member Names
We can look at the example immediately above to try to figure out how to get the enum members:
{
"2": "Second",
"First": "First",
"Second": 2,
"Other": "Second"
}
Here's what I came up with:
const e = MyEnum as any;
const names = Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
Member Values
Once, we have the names, we can loop over them to get the corresponding value by doing:
const values = names.map(k => MyEnum[k]);
Extension Class
I think the best way to do this is to create your own functions (ex. EnumEx.getNames(MyEnum)). You can't add a function to an enum.
class EnumEx {
private constructor() {
}
static getNamesAndValues(e: any) {
return EnumEx.getNames(e).map(n => ({ name: n, value: e[n] as string | number }));
}
static getNames(e: any) {
return Object.keys(e).filter(k =>
typeof e[k] === "number"
|| e[k] === k
|| e[e[k]]?.toString() !== k
);
}
static getValues(e: any) {
return EnumEx.getNames(e).map(n => e[n] as string | number);
}
}
With TypeScript >= 2.4 you can define string enums:
enum Color {
RED = 'Red',
ORANGE = 'Orange',
YELLOW = 'Yellow',
GREEN = 'Green',
BLUE = 'Blue',
INDIGO = 'Indigo',
VIOLET = 'Violet'
}
JavaScript ES5 output:
var Color;
(function (Color) {
Color["RED"] = "Red";
Color["ORANGE"] = "Orange";
Color["YELLOW"] = "Yellow";
Color["GREEN"] = "Green";
Color["BLUE"] = "Blue";
Color["INDIGO"] = "Indigo";
Color["VIOLET"] = "Violet";
})(Color || (Color = {}));
Which is an object like this:
const Color = {
"RED": "Red",
"ORANGE": "Orange",
"YELLOW": "Yellow",
"GREEN": "Green",
"BLUE": "Blue",
"INDIGO": "Indigo",
"VIOLET": "Violet"
}
Thus, in the case of string enums, no need to filter things,
Object.keys(Color) and Object.values(Color) are enough:
const colorKeys = Object.keys(Color) as (keyof typeof Color)[];
console.log('colorKeys =', colorKeys);
// ["RED", "ORANGE", "YELLOW", "GREEN", "BLUE", "INDIGO", "VIOLET"]
const colorValues = Object.values(Color);
console.log('colorValues =', colorValues);
// ["Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet"]
colorKeys.map(colorKey => {
console.log(`color key = ${colorKey}, value = ${Color[colorKey]}`);
});
/*
color key = RED, value = Red
color key = ORANGE, value = Orange
color key = YELLOW, value = Yellow
color key = GREEN, value = Green
color key = BLUE, value = Blue
color key = INDIGO, value = Indigo
color key = VIOLET, value = Violet
*/
See online example on TypeScript playground
There is no concept of RTTI (runtime type information) in TypeScript (think: reflection) so in order to do this, knowledge of the transpiled JavaScript is required. So, assuming TypeScript 0.95:
enum MyEnum {
First, Second, Third
}
becomes:
var MyEnum;
(function(MyEnum) {
MyEnum[MyEnum["First"] = 0] = "First";
MyEnum[MyEnum["Second"] = 1] = "Second";
MyEnum[MyEnum["Third"] = 2] = "Third";
}
So, this is modeled as a regular object in javascript, where MyEnum.0 == "First" and MyEnum.First == 0. So, to enumerate all of the enum names, you need to get all properties that belong to the object and that are also not numbers:
for (var prop in MyEnum) {
if (MyEnum.hasOwnProperty(prop) &&
(isNaN(parseInt(prop)))) {
console.log("name: " + prop);
}
}
Ok, so now I've told you how to do it, I'm allowed to tell you this is a bad idea. You're not writing a managed language, so you can't bring these habits. It's still just plain old JavaScript. If I wanted to use a structure in JavaScript to populate some kind of choices list, I would use a plain old array. An enum is not the right choice here, pun intended. The goal of TypeScript is to generate idiomatic, pretty JavaScript. Using enums in this way does not preserve this goal.
You can add functions to get the names and indices of the enum:
enum MyEnum {
First,
Second,
Third
}
namespace MyEnum {
function isIndex(key):boolean {
const n = ~~Number(key);
return String(n) === key && n >= 0;
}
const _names:string[] = Object
.keys(MyEnum)
.filter(key => !isIndex(key));
const _indices:number[] = Object
.keys(MyEnum)
.filter(key => isIndex(key))
.map(index => Number(index));
export function names():string[] {
return _names;
}
export function indices():number[] {
return _indices;
}
}
console.log("MyEnum names:", MyEnum.names());
// Prints: MyEnum names: ["First", "Second", "Third"]
console.log("MyEnum indices:", MyEnum.indices());
// Prints: MyEnum indices: [0, 1, 2]
Note that you could just export the _names and _indices consts rather than exposing them through an exported function, but because the exported members are members of the enum it is arguably clearer to have them as functions so they are not confused with the actual enum members.
It would be nice if TypeScript generated something like this automatically for all enums.
I used the solution proposed by David Sherret and wrote an npm library you can use named enum-values...
Git: enum-values
// Suppose we have an enum
enum SomeEnum {
VALUE1,
VALUE2,
VALUE3
}
// names will be equal to: ['VALUE1', 'VALUE2', 'VALUE3']
var names = EnumValues.getNames(SomeEnum);
// values will be equal to: [0, 1, 2]
var values = EnumValues.getValues(SomeEnum);
A one-liner to get a list of entries (key-value objects/pairs):
Object.keys(MyEnum).filter(a=>a.match(/^\D/)).map(name=>({name, value: MyEnum[name] as number}));
enum MyEnum {
First, Second, Third, NUM_OF_ENUMS
}
for(int i = 0; i < MyEnum.NUM_OF_ENUMS; ++i) {
// do whatever you need to do.
}
If you want to associate strings values to your enum these methods don't works. To have a generic function you can do :
function listEnum(enumClass) {
var values = [];
for (var key in enumClass) {
values.push(enum[key]);
}
values.length = values.length / 2;
return values;
}
It's works because TypeScript will add keys in first step, and values in second step.
In TypeScript it's:
var listEnums = <T> (enumClass: any): T[]=> {
var values: T[] = [];
for (var key in enumClass) {
values.push(enumClass[key]);
}
values.length = values.length / 2;
return values;
};
var myEnum: TYPE[] = listEnums<TYPE>(TYPE);
joe's answer just made me realize that is much more easier to rely on the first N numeric keys than making more complex testings:
function getEnumMembers(myEnum): string[]
{
let members = []
for(let i:number = 0; true; i++) {
if(myEnum[i] === undefined) break
members.push(myEnum[i])
}
return members
}
enum Colors {
Red, Green, Blue
}
console.log(getEnumMembers(myEnum))
Iterating over an enum
String Enums are best used for this. Here is an example:
// This is a string enum
enum MyEnum {
First = 'First',
Second = 'Second',
Third = 'Third',
}
// An enum is a TS concept
// However his MyEnum compiles to JS object:
// {
// "First": "First",
// "Second": "Second",
// "Third": "Third"
// }
// Therefore we can get the keys in the following manner:
const keysArray = Object.keys(MyEnum);
for (const key of keysArray) {
console.log(key)
}
// [LOG]: "First"
// [LOG]: "Second"
// [LOG]: "Third"
A type-safe solution could be as follows:
enum Color {
Blue = 'blue',
Green = 'green'
}
enum MoreColor {
Yellow,
Red
}
function getEnumValues<T, K extends keyof T>(enumType: T): Array<T[K]> {
return getEnumKeys<T, K>(enumType).map((x) => enumType[x]);
}
function getEnumKeys<T, K extends keyof T>(enumType: T): Array<K> {
return Object.keys(enumType)
.filter((x) => Number.isNaN(Number(x)))
.map((x) => x as K);
}
// return type is Color[]
const colorValues = getEnumValues(Color); // ["blue", "green"]
// return type is MoreColor[]
const moreColorValues = getEnumValues(MoreColor); // [0, 1]
// return type is Array<"Blue" | "Green">
const colorKeys = getEnumKeys(Color); // ["Blue", "Green"]
// return type is Array<"Yellow" | "Red">
const moreColorKeys = getEnumKeys(MoreColor); // ["Yellow", "Red"]
But keep in mind that this solution does not force you to pass just enums to the function.
for nodejs:
const { isNumber } = require('util');
Object.values(EnumObject)
.filter(val => isNumber(val))
.map(val => {
// do your stuff
})
Hi i have collection which contains around 200 documents looks like
e.g
"_id": 0,
"name": "Demarcus Audette",
"scores": [
{
"type": "exam",
"score": 30.61740640636871
},
{
"type": "quiz",
"score": 14.23233821353732
},
{
"type": "homework",
"score": 31.41421298576332
},
{
"type": "homework",
"score": 30.09304792394713
}
]
now i wrote code like
DBCursor cursor = collection.find().sort(new BasicDBObject("scores.score":1));
while( cursor.hasNext() )
{
DBobject obj=cursor.next();
BasicDBList list=(BasicDBList) Bobj.get("scores");
// Now here i am getting list of documents which consists of an scores array and i need to remove 3rd elements of it and save collection.... but how to do?
if i use for loop like
for(int i=0;i<list.size();i++)
{
list.remove(2);------ it gives an error here
collection.save(obj);
}
}
Are you sure that you can sort it as 'scores.score'. As 'scores' is a list of objects you cant reference objects inside list using dot notation. Error should be on that line.
Edit:
DBCursor cursor = collection.find();
while ( cursor.hasNext()) {
DBObject dbObject = cursor.next();
BasicDBList dbList = (BasicDBList) (dbObject.get("score"));
//then use java Collections.sort() to sort the List (refer to two methods at the bottom)
dbList.remove(3);
collection.save(dbObject);
}
Use one of the following to sort the DBList
1 . Using Lambda expression
Collections.sort(dbList, (o1, o2) -> Double.compare(((BasicDBObject) o1).getDouble("score"), ((BasicDBObject) o2).getDouble("score")));
or java 7 <
Collections.sort(dbList, new Comparator<Object>() {
public int compare(Object o, Object o2) {
if (((BasicDBObject) o).getDouble("score") >= ((BasicDBObject) o2).getDouble("score")) {
return 1;
}
return -1;
}
});
See this link https://gist.github.com/machadolucas/5188447/raw/e3f5c44c2be756c6087809df63f7ea8f4682ace9/Mongo3_1.java
I`m has been
[some symbol for post this message)))]