Returning an empty vector of strings if key is not found

前端 未结 4 799
花落未央
花落未央 2021-01-13 09:34

I know it is a very bad idea, so other suggestions on how to do it efficiently will be well-received.

Here\'s the thing. I have map

相关标签:
4条回答
  • 2021-01-13 09:58

    1) Returning an iterator is a fine idea. When you do this, the natural way to indicate the "not found" case is to return the .end() iterator. This has the down-side that the abstraction is somewhat leaky: the caller has to be able to get at this .end() value in order to compare to it for error checking, and the returned iterator exposes a richer interface than you'd like (the client code shouldn't really play around with incrementing and decrementing the iterator).

    2) Returning an empty vector is as simple as creating an empty vector and returning it. Creating an empty vector = constructing a vector which is empty. This is what you get from - drum roll - the default constructor of the vector class.

    3) You don't need to, and shouldn't, implement the search loop yourself. The standard library already implements this for you. (There is a specialized find function for map s because of the key/value distinction. For sequences like list, vector and deque, prefer the free function std::find, which comes from <algorithm>.

    4) You should prefer to accept function parameters (when they are instances of classes, like std::string) and return data (especially complex things like a vector of strings) by const reference. Passing and returning by value implies a copy; sometimes the compiler can optimize this away, but it's not as reliable as we'd like. Besides, the reason you're using C++ in the first place is to have that level of control over things, right? If not, then don't torture yourself with it.

    However, you can't do that if you're going to return a newly-created value some of the time. Yet another way to design the interface is to return a pointer to the vector of strings (note that pointer arithmetic on these will be invalid) within the map, or a NULL pointer if the value is not found. This avoids copying and distinguishes a "not found" result from an actual empty vector within the data, but it means the client code has to deal with an icky raw pointer.

    5) Having 'return' in the name of a function is useless, as returning is what functions do. OTOH, it is a good idea to name things in a way that makes it evident why the parameters are what they are.

    6) With iterators for complex types, it is often a good idea to set up typedefs.

    Returning an iterator is as simple as:

    typedef map<string, vector<string> >::iterator graph_iterator;
    graph_iterator edges_named(const string& node_name) {
        return outgoing.find(node_name);
    }
    

    Returning a vector of strings is as simple as:

    typedef map<string, vector<string> >::iterator graph_iterator;
    vector<string> edges_named(const string& node_name) {
        graph_iterator it = outgoing.find(node_name);
        return it == outgoing.end() ? vector<string>() : it->second;
    }
    

    Returning a pointer is as simple as:

    typedef map<string, vector<string> >::iterator graph_iterator;
    vector<string>* edges_named(const string& node_name) {
        graph_iterator it = outgoing.find(node_name);
        return it == outgoing.end() ? NULL : &(it->second);
    }
    

    Choose wisely.

    0 讨论(0)
  • 2021-01-13 10:07

    Most of the time you don't need a copy of the vector to be returned, a const reference will do just as well. You can always make a copy later if you need to.

    Also you don't need to iterate through a map, they're optimized for searching with the find method.

    const vector<string> & returnEdges(string key)
    {
        map<string, vector<string> >::iterator it = outgoing.find(key);
        if (it == outgoing.end())
        {
            static vector<string> empty_vector;
            return empty_vector;
        }
        return it->second;
    }
    
    0 讨论(0)
  • 2021-01-13 10:07

    I think the operator [] can help you, it will return a empty value(a empty vector here). So all you need to do is

    vector<string> returnEdges(string key) 
    {
        return outgoing[key];
    }
    
    0 讨论(0)
  • 2021-01-13 10:10

    How about this:

    std::vector<std::string> find_by_key_maybe(const std::string & key)
    {
      std::map<std::string, std::vector<std::string>>::const_iterator it = themap.find(key);
      return it == themap.end() ? std::vector<std::string>() : it->second;
    }
    

    Or even, if themap is non-const, and you also wish to add an empty vector into the map:

    std::vector<std::string> find_by_key_and_insert_if_missing(const std::string & key)
    {
      return themap[key];
    }
    

    It's perfectly OK to return a vector by value, if that's what the situation calls for.

    0 讨论(0)
提交回复
热议问题