首页 \ 问答 \ 如何实现Swift 3 Dictionary(其中:)封闭(How to implement Swift 3 Dictionary first(where:) closure)

如何实现Swift 3 Dictionary(其中:)封闭(How to implement Swift 3 Dictionary first(where:) closure)

我在Swift 3中有一个[String:String]数组,我想在这个数组中找到一个特定项,具体取决于Key是否包含String值。

                let result = collection.first(where: ((key, value) -> Bool in
                    return key.contains("mystring")))

然而,Xcode一直告诉我它是'表达式列表中的预期表达式'。 我现在用Google搜索了一个小时,并且以包含或过滤方式使用此闭包的每个网站似乎都是正确的语法。

我在这里想念的是什么?


I have an [String:String] array in Swift 3 and I want to find a specific item in this array depending on whether the Key contains a String value.

                let result = collection.first(where: ((key, value) -> Bool in
                    return key.contains("mystring")))

However Xcode keeps telling me that it is 'Expected expression in list of expressions'. I googled for an hour now and every website that is using this closure in either a contains or filter manner seems to be the right syntax.

What am I missing here?


原文:https://stackoverflow.com/questions/42707849
更新时间:2022-08-31 16:08

最满意答案

我为你做了一点幻想。

我通常采取的第一步是提出AST模型:

namespace Ast
{
    enum Command  { NO_CMD, TARGET, SENSOR, PAIR };
    enum Modifier { NO_MODIFIER, ON, OFF, ERASE };

    struct ModifiedCommand
    {
        Command cmd  = NO_CMD;
        Modifier mod = NO_MODIFIER;
    };

    struct OtherCommand
    {
        std::string token;
        OtherCommand(std::string token = "") : token(std::move(token))
        { }
    };

    typedef boost::variant<int, double> Operand;

    typedef boost::variant<Operand, ModifiedCommand, OtherCommand> RpnMachineInstruction;
    typedef std::vector<RpnMachineInstruction> RpnMachineProgram;
}

正如您所看到的,我打算区分整数和操作数值的double,并且我将语法中没有主动描述的任何“其他”命令(如“HSSF”)视为自由形式的标记(大写字母)。

现在,我们将规则定义映射到此:

RpnGrammar() : RpnGrammar::base_type(_start)
{
    _start         = *_instruction;
    _instruction   = _operand | _mod_command | _other_command;

    _operand       = _strict_double | qi::int_;

    _mod_command   = _command >> _modifier;
    _other_command = qi::as_string [ +qi::char_("A-Z") ];

    // helpers
    _command.add("TARGET", Ast::TARGET)("SENSOR", Ast::SENSOR)("PAIR", Ast::PAIR);
    _modifier.add("ON", Ast::ON)("OFF", Ast::OFF)("ERASE", Ast::ERASE);
}

语法将结果解析为指令列表( Ast::RpnMachineProgram ),其中每条指令是操作数或操作(带修饰符的命令,或任何其他自由格式命令,如“HSSF”)。 以下是规则声明:

qi::rule<It, Ast::RpnMachineProgram(),     Skipper> _start;
qi::rule<It, Ast::RpnMachineInstruction(), Skipper> _instruction;
qi::rule<It, Ast::ModifiedCommand(),       Skipper> _mod_command;
qi::rule<It, Ast::Operand(),               Skipper> _operand;

// note: omitting the Skipper has the same effect as wrapping with `qi::lexeme`
qi::rule<It, Ast::OtherCommand()> _other_command;

qi::real_parser<double, boost::spirit::qi::strict_real_policies<double> > _strict_double;
qi::symbols<char, Ast::Command>  _command;
qi::symbols<char, Ast::Modifier> _modifier;

您可以看到它解析问题中的示例:

Parse succeeded, 10 stack instructions
int:0 int:1 'HSFF'
int:41 SENSOR [ON] 
int:1 double:12 'BH'
int:4 'LNON'

输出是使用示例访问者创建的,您可以将其用作解释器/执行器的灵感。

看到Live On Coliru

完整清单

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <fstream>

namespace qi = boost::spirit::qi;

namespace Ast
{
    enum Command  { NO_CMD, TARGET, SENSOR, PAIR };
    enum Modifier { NO_MODIFIER, ON, OFF, ERASE };

    struct ModifiedCommand
    {
        Command cmd  = NO_CMD;
        Modifier mod = NO_MODIFIER;
    };

    struct OtherCommand
    {
        std::string token;
        OtherCommand(std::string token = "") : token(std::move(token))
        { }
    };

    typedef boost::variant<int, double> Operand;

    typedef boost::variant<Operand, ModifiedCommand, OtherCommand> RpnMachineInstruction;
    typedef std::vector<RpnMachineInstruction> RpnMachineProgram;

    // for printing, you can adapt this to execute the stack instead
    struct Print : boost::static_visitor<std::ostream&>
    {
        Print(std::ostream& os) : os(os) {}
        std::ostream& os;

        std::ostream& operator()(Ast::Command cmd) const {
            switch(cmd) {
                case TARGET: return os << "TARGET" << " ";
                case SENSOR: return os << "SENSOR" << " ";
                case PAIR:   return os << "PAIR"   << " ";
                case NO_CMD: return os << "NO_CMD" << " ";
                default:     return os << "#INVALID_COMMAND#" << " ";
            }
        }

        std::ostream& operator()(Ast::Modifier mod) const {
            switch(mod) {
                case ON:          return os << "[ON]"          << " ";
                case OFF:         return os << "[OFF]"         << " ";
                case ERASE:       return os << "[ERASE]"       << " ";
                case NO_MODIFIER: return os << "[NO_MODIFIER]" << " ";
                default:    return os << "#INVALID_MODIFIER#" << " ";
            }
        }

        std::ostream& operator()(double d) const { return os << "double:" << d << " "; }
        std::ostream& operator()(int    i) const { return os << "int:"    << i << " "; }

        std::ostream& operator()(Ast::OtherCommand const& cmd) const {
            return os << "'" << cmd.token << "'\n";
        }

        std::ostream& operator()(Ast::ModifiedCommand const& cmd) const {
            (*this)(cmd.cmd);
            (*this)(cmd.mod);
            return os << "\n"; 
        }

        template <typename... TVariant>
        std::ostream& operator()(boost::variant<TVariant...> const& v) const { 
            return boost::apply_visitor(*this, v); 
        }
    };

}

BOOST_FUSION_ADAPT_STRUCT(Ast::ModifiedCommand, (Ast::Command, cmd)(Ast::Modifier, mod))

template <typename It, typename Skipper = qi::space_type>
struct RpnGrammar : qi::grammar<It, Ast::RpnMachineProgram(), Skipper>
{
    RpnGrammar() : RpnGrammar::base_type(_start)
    {
        _command.add("TARGET", Ast::TARGET)("SENSOR", Ast::SENSOR)("PAIR", Ast::PAIR);
        _modifier.add("ON", Ast::ON)("OFF", Ast::OFF)("ERASE", Ast::ERASE);

        _start         = *_instruction;
        _instruction   = _operand | _mod_command | _other_command;

        _operand       = _strict_double | qi::int_;

        _mod_command   = _command >> _modifier;
        _other_command = qi::as_string [ +qi::char_("A-Z") ];
    }

  private:
    qi::rule<It, Ast::RpnMachineProgram(),     Skipper> _start;
    qi::rule<It, Ast::RpnMachineInstruction(), Skipper> _instruction;
    qi::rule<It, Ast::ModifiedCommand(),       Skipper> _mod_command;
    qi::rule<It, Ast::Operand(),               Skipper> _operand;

    // note: omitting the Skipper has the same effect as wrapping with `qi::lexeme`
    qi::rule<It, Ast::OtherCommand()> _other_command;

    qi::real_parser<double, boost::spirit::qi::strict_real_policies<double> > _strict_double;
    qi::symbols<char, Ast::Command>  _command;
    qi::symbols<char, Ast::Modifier> _modifier;
};

int main()
{
    std::ifstream ifs("input.txt");
    typedef boost::spirit::istream_iterator It;
    ifs.unsetf(std::ios::skipws);

    RpnGrammar<It> grammar;

    It f(ifs), l;
    Ast::RpnMachineProgram program;
    bool ok = qi::phrase_parse(f, l, grammar, qi::space, program);

    if (ok)
    {
        std::cout << "Parse succeeded, " << program.size() << " stack instructions\n";
        std::for_each(
                program.begin(),
                program.end(),
                Ast::Print(std::cout));
    }
    else
    {
        std::cout << "Parse failed\n";
    }

    if (f != l)
    {
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
    }
}

I have phantasized a little for you.

The first step I usually take is to come up with an AST model:

namespace Ast
{
    enum Command  { NO_CMD, TARGET, SENSOR, PAIR };
    enum Modifier { NO_MODIFIER, ON, OFF, ERASE };

    struct ModifiedCommand
    {
        Command cmd  = NO_CMD;
        Modifier mod = NO_MODIFIER;
    };

    struct OtherCommand
    {
        std::string token;
        OtherCommand(std::string token = "") : token(std::move(token))
        { }
    };

    typedef boost::variant<int, double> Operand;

    typedef boost::variant<Operand, ModifiedCommand, OtherCommand> RpnMachineInstruction;
    typedef std::vector<RpnMachineInstruction> RpnMachineProgram;
}

As you can see I intend to distinguish integers and double for operand values, and I treat any "other" commands (like "HSSF") that wasn't actively described in your grammar as free-form tokens (uppercase alphabetical).

Now, we map the rule definitions onto this:

RpnGrammar() : RpnGrammar::base_type(_start)
{
    _start         = *_instruction;
    _instruction   = _operand | _mod_command | _other_command;

    _operand       = _strict_double | qi::int_;

    _mod_command   = _command >> _modifier;
    _other_command = qi::as_string [ +qi::char_("A-Z") ];

    // helpers
    _command.add("TARGET", Ast::TARGET)("SENSOR", Ast::SENSOR)("PAIR", Ast::PAIR);
    _modifier.add("ON", Ast::ON)("OFF", Ast::OFF)("ERASE", Ast::ERASE);
}

The grammar parses the result into a list of instructions (Ast::RpnMachineProgram), where each instruction is either an operand or an operation (a command with modifier, or any other free-form command like "HSSF"). Here are the rule declarations:

qi::rule<It, Ast::RpnMachineProgram(),     Skipper> _start;
qi::rule<It, Ast::RpnMachineInstruction(), Skipper> _instruction;
qi::rule<It, Ast::ModifiedCommand(),       Skipper> _mod_command;
qi::rule<It, Ast::Operand(),               Skipper> _operand;

// note: omitting the Skipper has the same effect as wrapping with `qi::lexeme`
qi::rule<It, Ast::OtherCommand()> _other_command;

qi::real_parser<double, boost::spirit::qi::strict_real_policies<double> > _strict_double;
qi::symbols<char, Ast::Command>  _command;
qi::symbols<char, Ast::Modifier> _modifier;

You can see it parse the sample from the question:

Parse succeeded, 10 stack instructions
int:0 int:1 'HSFF'
int:41 SENSOR [ON] 
int:1 double:12 'BH'
int:4 'LNON'

The output is created with a sample visitor that you could use as inspiration for an interpreter/executor.

See it Live On Coliru

Full Listing

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <fstream>

namespace qi = boost::spirit::qi;

namespace Ast
{
    enum Command  { NO_CMD, TARGET, SENSOR, PAIR };
    enum Modifier { NO_MODIFIER, ON, OFF, ERASE };

    struct ModifiedCommand
    {
        Command cmd  = NO_CMD;
        Modifier mod = NO_MODIFIER;
    };

    struct OtherCommand
    {
        std::string token;
        OtherCommand(std::string token = "") : token(std::move(token))
        { }
    };

    typedef boost::variant<int, double> Operand;

    typedef boost::variant<Operand, ModifiedCommand, OtherCommand> RpnMachineInstruction;
    typedef std::vector<RpnMachineInstruction> RpnMachineProgram;

    // for printing, you can adapt this to execute the stack instead
    struct Print : boost::static_visitor<std::ostream&>
    {
        Print(std::ostream& os) : os(os) {}
        std::ostream& os;

        std::ostream& operator()(Ast::Command cmd) const {
            switch(cmd) {
                case TARGET: return os << "TARGET" << " ";
                case SENSOR: return os << "SENSOR" << " ";
                case PAIR:   return os << "PAIR"   << " ";
                case NO_CMD: return os << "NO_CMD" << " ";
                default:     return os << "#INVALID_COMMAND#" << " ";
            }
        }

        std::ostream& operator()(Ast::Modifier mod) const {
            switch(mod) {
                case ON:          return os << "[ON]"          << " ";
                case OFF:         return os << "[OFF]"         << " ";
                case ERASE:       return os << "[ERASE]"       << " ";
                case NO_MODIFIER: return os << "[NO_MODIFIER]" << " ";
                default:    return os << "#INVALID_MODIFIER#" << " ";
            }
        }

        std::ostream& operator()(double d) const { return os << "double:" << d << " "; }
        std::ostream& operator()(int    i) const { return os << "int:"    << i << " "; }

        std::ostream& operator()(Ast::OtherCommand const& cmd) const {
            return os << "'" << cmd.token << "'\n";
        }

        std::ostream& operator()(Ast::ModifiedCommand const& cmd) const {
            (*this)(cmd.cmd);
            (*this)(cmd.mod);
            return os << "\n"; 
        }

        template <typename... TVariant>
        std::ostream& operator()(boost::variant<TVariant...> const& v) const { 
            return boost::apply_visitor(*this, v); 
        }
    };

}

BOOST_FUSION_ADAPT_STRUCT(Ast::ModifiedCommand, (Ast::Command, cmd)(Ast::Modifier, mod))

template <typename It, typename Skipper = qi::space_type>
struct RpnGrammar : qi::grammar<It, Ast::RpnMachineProgram(), Skipper>
{
    RpnGrammar() : RpnGrammar::base_type(_start)
    {
        _command.add("TARGET", Ast::TARGET)("SENSOR", Ast::SENSOR)("PAIR", Ast::PAIR);
        _modifier.add("ON", Ast::ON)("OFF", Ast::OFF)("ERASE", Ast::ERASE);

        _start         = *_instruction;
        _instruction   = _operand | _mod_command | _other_command;

        _operand       = _strict_double | qi::int_;

        _mod_command   = _command >> _modifier;
        _other_command = qi::as_string [ +qi::char_("A-Z") ];
    }

  private:
    qi::rule<It, Ast::RpnMachineProgram(),     Skipper> _start;
    qi::rule<It, Ast::RpnMachineInstruction(), Skipper> _instruction;
    qi::rule<It, Ast::ModifiedCommand(),       Skipper> _mod_command;
    qi::rule<It, Ast::Operand(),               Skipper> _operand;

    // note: omitting the Skipper has the same effect as wrapping with `qi::lexeme`
    qi::rule<It, Ast::OtherCommand()> _other_command;

    qi::real_parser<double, boost::spirit::qi::strict_real_policies<double> > _strict_double;
    qi::symbols<char, Ast::Command>  _command;
    qi::symbols<char, Ast::Modifier> _modifier;
};

int main()
{
    std::ifstream ifs("input.txt");
    typedef boost::spirit::istream_iterator It;
    ifs.unsetf(std::ios::skipws);

    RpnGrammar<It> grammar;

    It f(ifs), l;
    Ast::RpnMachineProgram program;
    bool ok = qi::phrase_parse(f, l, grammar, qi::space, program);

    if (ok)
    {
        std::cout << "Parse succeeded, " << program.size() << " stack instructions\n";
        std::for_each(
                program.begin(),
                program.end(),
                Ast::Print(std::cout));
    }
    else
    {
        std::cout << "Parse failed\n";
    }

    if (f != l)
    {
        std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
    }
}

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。