Swift:通过比较类型过滤协议数组(Swift: filter protocol array by comparing types)
(第一篇文章)
通常我能在这里或其他地方找到答案,但这次没有运气=(
问题:在Swift中,如何通过作为函数参数提供的实现类型过滤协议类型的数组?
protocol Aprotocol { var number:Int { get set } } class Aclass: Aprotocol { var number = 1 } class AnotherClass: Aprotocol { var number = 1 } var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ] func foo (parameter:Aprotocol) -> Int { return array.filter({ /* p in p.self == parameter.self */ }).count } var bar:Aprotocol = // Aclass() or AnotherClass() var result:Int = foo(bar) // should return 2 or 1, depending on bar type
也许这根本不是正确的方法?
谢谢!
(first post)
usually im able to find answers here or elsewhere but no luck this time =(
Question: in Swift, how do you filter an array that is of a protocol type by an implementing type supplied as a function parameter?
protocol Aprotocol { var number:Int { get set } } class Aclass: Aprotocol { var number = 1 } class AnotherClass: Aprotocol { var number = 1 } var array:[Aprotocol] = [ Aclass(), AnotherClass(), Aclass() ] func foo (parameter:Aprotocol) -> Int { return array.filter({ /* p in p.self == parameter.self */ }).count } var bar:Aprotocol = // Aclass() or AnotherClass() var result:Int = foo(bar) // should return 2 or 1, depending on bar type
maybe this is not the right approach at all?
thanks!
原文:https://stackoverflow.com/questions/30823554
最满意答案
我可以看到这个命令的一些问题:
db.location.aggregate([ {$match : { FirstName: { $nin : [" "] } } }, {$group: {_id : "$DeviceId" } }, {$project: { "DeviceId" : 1 } } ])
$match
阶段与您问题中提供的文档不匹配,因为您提供的文档具有"FirstName" : " "
因此该文档将匹配$in
而不是$nin
如果
$match
阶段更改为$in
那么它将发出一个文档,分组阶段将有一些工作,但分组阶段只配置为返回_id
属性,因此它返回以下中间文档:{ "_id" : "89984320001499681816" }
$project
阶段尝试投影"DeviceId"
但分组阶段的结果仅包含_id
属性,因此您无法从该文档投影DeviceId
属性。当您的聚合管道到达
forEach
函数时,文档中没有DeviceId,FirstName或LastName属性。要进一步了解聚合管道内发生的情况,您可以运行此查询:
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$project: { "DeviceId" : 1, FirstName: 1, LastName: 1 } } ]).forEach( function(obj) { print(obj); } );
或者,只需自己运行管道中的每个阶段并查看每个状态的输出,因为这将成为下一阶段的输入。 所以,例如:
这个命令......
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } } ])
...返回:
{ "_id" : ObjectId("59d13b64c26584cd8b7a15c8"), "CreationDateTime" : ISODate("2017-09-26T06:39:29.105Z"), "DeviceId" : "89984320001499681816", "UserId" : UUID("bca0db12-2246-49a5-8703-b03fee45e50f"), "FirstName" : " ", "LastName" : "" }
这个命令......
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$group: {_id : "$DeviceId" } } ])
...返回:
{ "_id" : "89984320001499681816" }
这个命令......
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$group: {_id : "$DeviceId" } }, {$project: { "DeviceId" : 1 } } ])
...返回:
{ "_id" : "89984320001499681816" }
这应该清楚地表明,一旦添加
$group
阶段,您将丢失DeviceId,FirstName和LastName属性,因此它们无法在forEach
函数中打印。I can see a few issues with this command:
db.location.aggregate([ {$match : { FirstName: { $nin : [" "] } } }, {$group: {_id : "$DeviceId" } }, {$project: { "DeviceId" : 1 } } ])
- The
$match
stage will not match the document supplied in your question because the document you supplied has"FirstName" : " "
so that document would be matched by$in
but not by$nin
If the
$match
stage was changed to$in
then it would emit a document and the grouping stage would have something to work on but the grouping stage is only configured to return an_id
attribute so it returns the following intermediate document:{ "_id" : "89984320001499681816" }
The
$project
stage attempts to project"DeviceId"
but the result of the grouping stage contains only an_id
attribute so you cannot project aDeviceId
attribute from that document.By the time your aggregation pipeline reaches the
forEach
funciton there is no DeviceId, FirstName or LastName attribute in the documents.To further understand what's happening inside the aggregation pipeline you could run this query:
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$project: { "DeviceId" : 1, FirstName: 1, LastName: 1 } } ]).forEach( function(obj) { print(obj); } );
Or, just run each stage in the pipeline on its own and review the output of each state since that becomes the input to the next stage. So, for example:
This command ...
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } } ])
... returns:
{ "_id" : ObjectId("59d13b64c26584cd8b7a15c8"), "CreationDateTime" : ISODate("2017-09-26T06:39:29.105Z"), "DeviceId" : "89984320001499681816", "UserId" : UUID("bca0db12-2246-49a5-8703-b03fee45e50f"), "FirstName" : " ", "LastName" : "" }
This command ...
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$group: {_id : "$DeviceId" } } ])
... returns:
{ "_id" : "89984320001499681816" }
This command ...
db.location.aggregate([ {$match : { FirstName: { $in : [" "] } } }, {$group: {_id : "$DeviceId" } }, {$project: { "DeviceId" : 1 } } ])
... returns:
{ "_id" : "89984320001499681816" }
This should make clear that once you add in the
$group
stage you lose the DeviceId, FirstName and LastName attributes hence they are not available for you to print in theforEach
function.
相关问答
更多-
蒙克斯的文件是迟钝的。 一位互联网英雄写道.col访问本机mongodb驱动程序,我可以做屎。 然而,我必须再次将它包装在一个承诺中,尽管没有probs。 var sessionSeen = yield new Promise(function (resolve, reject) { users.col.aggregate([ { $match: ...
-
在光标上调用toArray而不是forEach : var a = db.my_collection.find( {timestamp : {$gt: 1343032491799}}, {_id:0,sid:1}).limit(20) .toArray().map(function(o){return o.sid;}) UPDATE 似乎您可以跳过toArray并直接转到map因为光标直接提供了该方法: var a = db.my_collection.find( {timesta ...
-
你可以使用$exists像这样: db.tweets.find( {"coordinates": {$exists: true}}, {"_id":0, "coordinates.coordinates": 1} ); you can use $exists like this: db.tweets.find( {"coordinates": {$exists: true}}, {"_id":0, "coordinates.coordinates": 1} );
-
如何从MongoDB聚合中读取未定义对象的属性?(How to read property of undefined object from MongoDB aggregation?)[2022-04-22]
你的函数getTotalTeamScore正在执行mongodb聚合函数,它是异步操作。 因此它不会立即返回结果,但在聚合返回DB记录之前,您的函数将被撤消。 所以你需要使用回调。 首先修改你的getTotalTeamScore函数,如下所示: module.exports.getTotalTeamScore = function (callback) { User.aggregate([ { $group: { _id: "$team", ... -
我可以看到这个命令的一些问题: db.location.aggregate([ {$match : { FirstName: { $nin : [" "] } } }, {$group: {_id : "$DeviceId" } }, {$project: { "DeviceId" : 1 } } ]) $match阶段与您问题中提供的文档不匹配,因为您提供的文档具有"FirstName" : " "因此该文档将匹配$in而不是$nin 如果$match阶段更改为$in那么它将发出一个文档,分组阶段 ...
-
这两个语句在核心API级别基本相同,即获取光标并转换结果。 然而,性能有一个“核心”差异: .forEach()将“一次一个”转换游标结果并处理它提供的迭代器函数。 .fetch()从光标“一次性”获取“数组”,这意味着它在一次命中中都是“内存中”。 所以无论如何,在从查询的光标获取“核心”操作时,实际上“更快”。 但是,不评估每个游标迭代的“表达式”可能会“稍微快一点”,因此.fetch()可能在这里赢得“小”。 当然,最大的问题是“现在一切都在记忆中”,因此需要考虑“开销”。 同样,在.fetch() ...
-
如何在forEach函数中检查mongodb文件中是否存在属性?(How to check if attribute exists in mongodb document in forEach function?)[2022-12-26]
Mongo shell是一个JavaScript shell,因此支持大多数标准JavaScript方法。 您可以像在JavaScript中的任何常规对象上一样检查属性是否存在 - 使用hasOwnProperty()方法: db.testData.find({}).forEach(function(x){ if (x.hasOwnProperty('name')) { // Do something } }) Mongo shell is a JavaScript she ... -
查询中的Mongodb $(Mongodb $within query)[2022-03-17]
引号不是问题,这只是有效的JSON。 问题是,minimongo还没有实现$。 Matt Debergalis 评论Minimongo的不完整状态 (2012年10月23日): 流行谈话最近的流量提醒我,minimongo带有一个健康的改进和扩展愿望清单。 [...] $ near,$ within和$ maxDistance。 您可能有更好的运气在您具有“真正的”mongodb访问权限的服务器中执行此操作,但如果客户端存储不具有相同的功能,我不确定它是如何工作的。 Minimongo的源代码可用 。 也许 ... -
您无法使用聚合管道执行此操作。 您应该了解MongoDB聚合是应用于集合的一系列特殊运算符。 当您执行聚合管道时,MongoDB将运算符彼此管道连接,即运算符的输出成为以下运算符的输入。 每个运算符的结果是一个新的文档集合。 因此,您在上面尝试实现的内容可以简单地重写为以下管道,而无需首先创建文档数组: var collection = db.collection('member'), pipeline = [ { "$match": { createdDate: currentD ...
-
mongoDbHandleLoad()包含异步代码(对MongoDB的调用),因此它会在代码到达行return JSON.stringify(docs[docs.length-1]);之前返回undefined return JSON.stringify(docs[docs.length-1]); 。 你应该使用回调或Promises来取回你的结果。 我想首先你应该研究一下Javascript中的异步代码,特别是Node.js的约定。 mongoDbHandleLoad() contains asynchr ...