Mapa de Multikey particionado -- ++ campo con c++11 campo con lookup campo con boost campo con hash-map camp codereview Relacionados El problema

Partitioned Multikey Map


11
vote

problema

Español

A continuación se muestra el código para lo que he llamado un 9988776665544333 . Esto tiene dos facetas principales:

  • permitiendo una búsqueda basada en las llaves de múltiples longitudes y de múltiples tipos. Por ejemplo:

typedef partitioned_multitype_map<int32_t, std::string, int64_t, double> map_t;

permitiría las claves de cualquier longitud 1 a un máximo (especificado), donde cada miembro En la clave es uno de los tipos de plantillas.

  • La segunda faceta es que particiona las llaves basadas en la longitud, lo que da fácil acceso a todos los pares de clave / valor de una longitud de clave dada.

Estoy buscando comentarios o críticas, pero en particular, hay un poco de duplicación de código que se encuentra alrededor. Simplemente debido a la complejidad de los tipos, tengo algunos problemas para tratar de reducirlo, por lo que cualquier cosa que esté dirigida a ese efecto sería genial.

  /*! file partitioned_multitype_map.hpp  *  rief Implementation of a compile time checked multi-key multi-value store.  *  *  A partitioned_multitype_map defines a multi-key multi-value store. The types   *  that the keys can store  are specified at compile time via variadic template   *  parameters Args...  *  There are a few concepts that must be adhered to:  *    1) Each type that is to be part of a key must be Hashable.  *    2) Each type that is to be part of a key must be equality comparable   *       (using ==).  *    3) At least one of the types must be DefaultConstructable.  *    4) Each type must be either CopyConstructible or MoveConstructable.  *  *  Currently, the values must correspond to the types that are stored as keys;   *  that is keys and values are composed of the same set of types.   *    *  The map is partitioned on key length to make it easy to get all keys (and   *  (associated values) of a given length.  *  *  The current API is -slightly- awkward as we have to store the inserted   *  key iterator to be able to insert a value into that spot. Variadic templates   *  makes creating a nice API for this more difficult.   *  *  Finally, note that this container isn't parameterized on an Allocator,   *  and hence will use std::allocator for all allocations.  *   */  #ifndef PARTITIONED_MULTI_TYPE_MAP_HPP_ #define PARTITIONED_MULTI_TYPE_MAP_HPP_  #include <algorithm> #include <cstdint> #include <functional> #include <numeric> #include <string> #include <unordered_map> #include <utility> #include <vector>  #include <boost/functional/hash.hpp> #include <boost/variant.hpp> #include <boost/optional.hpp>  namespace multi_container  {  template <typename... Args> class partitioned_multitype_map  { public:      using variant_type = boost::variant<Args...>;     using key_type     = std::vector<variant_type>;      using mapped_type  = std::vector<variant_type>;   private:      // Internal struct that is used to hash keys that the     // underlying map will hold.     struct hasher_      {         std::size_t operator()(const key_type& k) const         {             return boost::hash_range(k.begin(), k.end());         }     };      // Internal struct to be used for equality comparison of keys.     // Keys compare equal if they are the same size and each of the     // elements within the keys compares equal (order is significant).     struct equality_compare_     {         bool operator()(const key_type& k1, const key_type& k2) const         {             if(k1.size() != k2.size())                return false;             return std::equal(std::begin(k1), std::end(k1), std::begin(k2));          }     };      using hashmap_type   = std::unordered_map<key_type, mapped_type,                                                hasher_, equality_compare_>;      using partition_type = std::pair<std::uint8_t, hashmap_type>;     using storage_type   = std::vector<partition_type>;       storage_type container;  public:      // The maximum number of keys we're allowing. There isn't really a technical limitation     // to this limit, but hashing starts to become quite expensive. Could be removed     // at a later date with almost no impact on the rest of the code however, as it     // is only used in static_assert currently.     constexpr static std::uint8_t max_key_size =          std::numeric_limits<std::uint8_t>::max();      using size_type            = typename hashmap_type::size_type;     using difference_type      = typename hashmap_type::difference_type;     using hasher               = hasher_;     using key_equal            = equality_compare_;     using inner_iterator       = typename hashmap_type::iterator;     using const_inner_iterator = typename hashmap_type::const_iterator;      partitioned_multitype_map() = default;     ~partitioned_multitype_map() = default;      /*! rief Emplaces the key defined in args into the container, default constructing      *         the value that it maps to.      *        *  param args : The key (comprising of 1 or more elements) to be inserted.       *   eturn A pair where the first element is the iterator where the key was       *          inserted, and a boolean specifying if the key was inserted or not.      *          If the key already exists, it returns an iterator to the key and false.     */     template <typename... Keys>     auto emplace_key(Keys&&... args) -> decltype(container[0].second.emplace(args...))     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = static_cast<std::uint8_t>(key.size());         auto it = std::find_if(container.begin(), container.end(),                [=](const partition_type& p) { return p.first == k_size; });          if(it == container.end()) {             hashmap_type inner;             inner.emplace(std::move(key), mapped_type());              container.emplace_back(                     std::make_pair(k_size, std::move(inner)));             auto where = container.back().second.begin();             return std::make_pair(where, true);         } else {             hashmap_type& inner = it->second;             auto found = inner.find(key);             if(found != inner.end()) {                 return std::make_pair(found, false);             }             return inner.emplace(std::move(key), mapped_type());         }     }      /*! rief Sets the key pointed at by where to the values contained in args.      *         This assumes that the iterator passed in is a valid iterator (for       *         example, one returned by emplace_key). Behaviour is undefined if       *         the iterator does not point into the container.      *        *  param where: An iterator pointing at the key to set the value of.      *  param args: The value(s) (comprising 1 or more) to be mapped to the key       *               pointed to by where.     */     template <typename... Values>     void insert_value(inner_iterator where, Values&&... args)     {         mapped_type v {std::forward<Values>(args)...};         where->second = std::move(v);     }       /*! rief Checks the container for the existence of a given key.      *        *  param args: The key to search for.       *   eturns true if the given key exists in the container, false otherwise.     */     template <typename... Keys>      bool contains_key(Keys&&... args)     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();            auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return false;         }          hashmap_type& inner = it->second;         return inner.find(key) != inner.end();     }      /*! rief Returns a copy of the value corresponding to the given key.      *        *  param args: The key to search for.      *   eturns A optional copy of the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.      *  Note that this returns a boost::optional<> instead of a pair of iterators.      *  This is primarily because the keys are thought of as a "single" entity      *  instead of a container in their own right.     */     template <typename... Keys>     boost::optional<mapped_type> get_value(Keys&&... args) const     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type>();         }          return boost::optional<mapped_type>(found->second);     }      /*! rief Returns a reference to the value corresponding to the given key.      *        *  param args: The key to search for.      *   eturns An optional reference to the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.     */     template <typename... Keys>     boost::optional<mapped_type&> get_value(Keys&&... args)      {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type&>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type&>();         }          return boost::optional<mapped_type&>(found->second);     }      /*! rief Returns a const reference to the value corresponding to the given key.      *        *  param args: The key to search for.      *   eturns An optional reference to the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.     */     template <typename... Keys>     const boost::optional<mapped_type&> get_value(Keys&&... args) const     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type&>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type&>();         }          return boost::optional<mapped_type&>(found->second);     }      bool empty() const     {         return container.empty();     }      size_type size() const     {         size_type sum = 0;         for(const auto& p : container) {             sum += p.second.size();         }         return sum;     }      void clear()     {         container.clear();     }                      /*! rief Returns the number of keys in the container that have a given length.       *              *  param length The length of the keys to search for.      *   eturn The number of keys of the specified length, or 0 if no keys of      *          the given length exist.     */     std::size_t num_keys(std::uint8_t length)     {         auto it = std::find_if(container.begin(), container.end(),             [=](const partition_type& p) { return p.first == length; });         if(it != container.end()) {             return it->second.size();         }         return 0;      }      /*! rief Returns a pair of iterators to the beginning/end of the map       *         containing keys of a given length.      *      *  param length The length of the keys to search for.      *   eturn A pair of const iterators pointing to the beginning and end       *          of the map.     */     std::pair<const_inner_iterator, const_inner_iterator>     all_values_length(std::uint8_t length) const     {         auto it = std::find_if(container.begin(), container.end(),            [=](const partition_type& p) { return p.first == length; });         if(it != container.end()) {            return std::make_pair(it->second.begin(), it->second.end());         }         return std::make_pair(const_inner_iterator(), const_inner_iterator());     }  }; // end class partitioned_multitype_map  } // end namespace multi_container   
Original en ingles

Below is the code for what I've called a partitioned_multitype_map. This has two major facets:

  • Allowing a lookup based on keys of multiple lengths and of multiple types. For example:

typedef partitioned_multitype_map<int32_t, std::string, int64_t, double> map_t;

would allow keys of any length 1 to a (specified) maximum, where each member in the key is one of the template types.

  • The second facet is that it partitions keys based on length, giving easy access to all key/value pairs of a given key length.

I'm looking for any comments or criticisms, but particularly, there is quite a bit of code duplication lying around. Simply because of the complexity of the types, I'm having some trouble trying to reduce it, so anything that's directed to that effect would be great.

/*! \file partitioned_multitype_map.hpp  *  \brief Implementation of a compile time checked multi-key multi-value store.  *  *  A partitioned_multitype_map defines a multi-key multi-value store. The types   *  that the keys can store  are specified at compile time via variadic template   *  parameters Args...  *  There are a few concepts that must be adhered to:  *    1) Each type that is to be part of a key must be Hashable.  *    2) Each type that is to be part of a key must be equality comparable   *       (using ==).  *    3) At least one of the types must be DefaultConstructable.  *    4) Each type must be either CopyConstructible or MoveConstructable.  *  *  Currently, the values must correspond to the types that are stored as keys;   *  that is keys and values are composed of the same set of types.   *    *  The map is partitioned on key length to make it easy to get all keys (and   *  (associated values) of a given length.  *  *  The current API is -slightly- awkward as we have to store the inserted   *  key iterator to be able to insert a value into that spot. Variadic templates   *  makes creating a nice API for this more difficult.   *  *  Finally, note that this container isn't parameterized on an Allocator,   *  and hence will use std::allocator for all allocations.  *   */  #ifndef PARTITIONED_MULTI_TYPE_MAP_HPP_ #define PARTITIONED_MULTI_TYPE_MAP_HPP_  #include <algorithm> #include <cstdint> #include <functional> #include <numeric> #include <string> #include <unordered_map> #include <utility> #include <vector>  #include <boost/functional/hash.hpp> #include <boost/variant.hpp> #include <boost/optional.hpp>  namespace multi_container  {  template <typename... Args> class partitioned_multitype_map  { public:      using variant_type = boost::variant<Args...>;     using key_type     = std::vector<variant_type>;      using mapped_type  = std::vector<variant_type>;   private:      // Internal struct that is used to hash keys that the     // underlying map will hold.     struct hasher_      {         std::size_t operator()(const key_type& k) const         {             return boost::hash_range(k.begin(), k.end());         }     };      // Internal struct to be used for equality comparison of keys.     // Keys compare equal if they are the same size and each of the     // elements within the keys compares equal (order is significant).     struct equality_compare_     {         bool operator()(const key_type& k1, const key_type& k2) const         {             if(k1.size() != k2.size())                return false;             return std::equal(std::begin(k1), std::end(k1), std::begin(k2));          }     };      using hashmap_type   = std::unordered_map<key_type, mapped_type,                                                hasher_, equality_compare_>;      using partition_type = std::pair<std::uint8_t, hashmap_type>;     using storage_type   = std::vector<partition_type>;       storage_type container;  public:      // The maximum number of keys we're allowing. There isn't really a technical limitation     // to this limit, but hashing starts to become quite expensive. Could be removed     // at a later date with almost no impact on the rest of the code however, as it     // is only used in static_assert currently.     constexpr static std::uint8_t max_key_size =          std::numeric_limits<std::uint8_t>::max();      using size_type            = typename hashmap_type::size_type;     using difference_type      = typename hashmap_type::difference_type;     using hasher               = hasher_;     using key_equal            = equality_compare_;     using inner_iterator       = typename hashmap_type::iterator;     using const_inner_iterator = typename hashmap_type::const_iterator;      partitioned_multitype_map() = default;     ~partitioned_multitype_map() = default;      /*! \brief Emplaces the key defined in args into the container, default constructing      *         the value that it maps to.      *        *  \param args : The key (comprising of 1 or more elements) to be inserted.       *  \return A pair where the first element is the iterator where the key was       *          inserted, and a boolean specifying if the key was inserted or not.      *          If the key already exists, it returns an iterator to the key and false.     */     template <typename... Keys>     auto emplace_key(Keys&&... args) -> decltype(container[0].second.emplace(args...))     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = static_cast<std::uint8_t>(key.size());         auto it = std::find_if(container.begin(), container.end(),                [=](const partition_type& p) { return p.first == k_size; });          if(it == container.end()) {             hashmap_type inner;             inner.emplace(std::move(key), mapped_type());              container.emplace_back(                     std::make_pair(k_size, std::move(inner)));             auto where = container.back().second.begin();             return std::make_pair(where, true);         } else {             hashmap_type& inner = it->second;             auto found = inner.find(key);             if(found != inner.end()) {                 return std::make_pair(found, false);             }             return inner.emplace(std::move(key), mapped_type());         }     }      /*! \brief Sets the key pointed at by where to the values contained in args.      *         This assumes that the iterator passed in is a valid iterator (for       *         example, one returned by emplace_key). Behaviour is undefined if       *         the iterator does not point into the container.      *        *  \param where: An iterator pointing at the key to set the value of.      *  \param args: The value(s) (comprising 1 or more) to be mapped to the key       *               pointed to by where.     */     template <typename... Values>     void insert_value(inner_iterator where, Values&&... args)     {         mapped_type v {std::forward<Values>(args)...};         where->second = std::move(v);     }       /*! \brief Checks the container for the existence of a given key.      *        *  \param args: The key to search for.       *  \returns true if the given key exists in the container, false otherwise.     */     template <typename... Keys>      bool contains_key(Keys&&... args)     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();            auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return false;         }          hashmap_type& inner = it->second;         return inner.find(key) != inner.end();     }      /*! \brief Returns a copy of the value corresponding to the given key.      *        *  \param args: The key to search for.      *  \returns A optional copy of the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.      *  Note that this returns a boost::optional<> instead of a pair of iterators.      *  This is primarily because the keys are thought of as a "single" entity      *  instead of a container in their own right.     */     template <typename... Keys>     boost::optional<mapped_type> get_value(Keys&&... args) const     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type>();         }          return boost::optional<mapped_type>(found->second);     }      /*! \brief Returns a reference to the value corresponding to the given key.      *        *  \param args: The key to search for.      *  \returns An optional reference to the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.     */     template <typename... Keys>     boost::optional<mapped_type&> get_value(Keys&&... args)      {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type&>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type&>();         }          return boost::optional<mapped_type&>(found->second);     }      /*! \brief Returns a const reference to the value corresponding to the given key.      *        *  \param args: The key to search for.      *  \returns An optional reference to the value corresponding to the given key.      *           This is the value if found, or a default-constructed value if not.     */     template <typename... Keys>     const boost::optional<mapped_type&> get_value(Keys&&... args) const     {         static_assert(sizeof...(args) < max_key_size, "Too many keys specified");          key_type key {std::forward<Keys>(args)...};         const std::uint8_t k_size = key.size();          auto it = std::find_if(container.begin(), container.end(),                 [=](const partition_type& p) { return p.first == k_size; });         if(it == container.end()) {            return boost::optional<mapped_type&>();         }          hashmap_type& inner = it->second;         auto found = inner.find(key);         if(found == inner.end()) {             return boost::optional<mapped_type&>();         }          return boost::optional<mapped_type&>(found->second);     }      bool empty() const     {         return container.empty();     }      size_type size() const     {         size_type sum = 0;         for(const auto& p : container) {             sum += p.second.size();         }         return sum;     }      void clear()     {         container.clear();     }                      /*! \brief Returns the number of keys in the container that have a given length.       *              *  \param length The length of the keys to search for.      *  \return The number of keys of the specified length, or 0 if no keys of      *          the given length exist.     */     std::size_t num_keys(std::uint8_t length)     {         auto it = std::find_if(container.begin(), container.end(),             [=](const partition_type& p) { return p.first == length; });         if(it != container.end()) {             return it->second.size();         }         return 0;      }      /*! \brief Returns a pair of iterators to the beginning/end of the map       *         containing keys of a given length.      *      *  \param length The length of the keys to search for.      *  \return A pair of const iterators pointing to the beginning and end       *          of the map.     */     std::pair<const_inner_iterator, const_inner_iterator>     all_values_length(std::uint8_t length) const     {         auto it = std::find_if(container.begin(), container.end(),            [=](const partition_type& p) { return p.first == length; });         if(it != container.end()) {            return std::make_pair(it->second.begin(), it->second.end());         }         return std::make_pair(const_inner_iterator(), const_inner_iterator());     }  }; // end class partitioned_multitype_map  } // end namespace multi_container 
              

Lista de respuestas

3
 
vote

Diría que el mayor problema con ello es el problema que está tratando de resolver. Una colección de objetos de tipos desconocidos es una cosa muy confusa e ineficiente. Una vez recuperado, uno debe determinar la identidad del objeto antes de decidir qué se puede hacer con él. Solo hay tres casos de uso real:

  • No sabe el tipo de objeto, pero sabe que tiene ciertas operaciones que puede realizar en él para hacer lo que necesita. En este caso, debe convertirlo en algo que usted sabe, definiendo un tipo de envoltura que puede encerrar cualquiera de los tipos deseados y manejar la lógica de compatibilidad.
  • Ni siquiera sabes lo que es que es el tipo de clave; Es suministrado por fuentes externas. En ese caso, use un tipo de envoltura para convertirlo en algo que usted sabe, como se sugiere anteriormente.
  • Usted ya sabe qué tipo de todo se supone que debe ser, en cuyo caso debe tener varias colecciones diferentes, una para cada tipo y recuperar objetos de la recopilación aplicable. (Incluso puede ponerlos a todos en la misma clase, donde tiene initialize8 y initialize9 o algo así, si realmente tiene que hacerlo).

En resumen, no hay necesidad de mapas de tipo multi-tipo. Si los usa, toda la escritura dinámica necesaria eliminará su código para siempre y, nunca debe ser borrado o borrado.

 

I'd say that the biggest problem with it is the problem it is trying to solve. A collection of objects of unknown types is a very confusing and inefficient thing. Once retrieved, one must then ascertain the identity of the object before deciding what can be done with it. There are only three real use cases:

  • You don't know the type of the object, but you know that it has certain operations you can perform on it to do what you need. In this case, you should turn it into something you do know, by defining a wrapper type that can enclose any of the desired types and handle the compatibility logic.
  • You don't even know what they type of the key is; it is supplied by external sources. In that case, use a wrapper type to turn it into something you do know, as suggested previously.
  • You already know what type everything is supposed to be, in which case you should have several different collections, one for each type, and retrieve objects from the applicable collection. (You could even put them all in the same class, where you have http_response.get_uri("location") and http_response.get_int("status-code") or some such thing, if you really have to.)

In short, there is no need for multi-type maps. If you use them, all the dynamic typing needed will plague your code forever and ever, never to be erased or blotted out.

 
 
       
       

Relacionados problema

3  Compara los dictos y récord de cambios  ( Compare dicts and record changes ) 
Mi objetivo es actualizar continuamente un objeto y registrar cualquier cambio y las veces que se hicieron. La entrada debe ser JSON, pero el formato de salid...

4  Un programa para mostrar, actualizar y guardar un diccionario como .csv  ( A program to display update and save a dictionary as csv ) 
Ahora estoy buscando comentarios en v2.0 de este programa en su lugar. Me gustaría algunos comentarios sobre mi código. ¿Qué malos hábitos tengo? ¿Qué c...

0  Acelerar el código basado en el mapa con vectores como valores  ( Speed up code based on map with vectors as values ) 
Siguiendo es la pieza de código que representa el cuello de botella de mi aplicación: #include <iostream> #include <chrono> #include <unordered_map> #inclu...

6  Hosth de descarga en columnas  ( Dump hash in columns ) 
Intenté responder a la pregunta "¿Cómo imprimir un hash en Perl, de modo que se imprimen 3 pares de valor clave en cada línea? " como este . Como obtuve u...

0  Base de datos de estudiantes  ( Database of students ) 
Al principio, tuve 9988777665544332 para contener std::list<Student> students , pero como hay más de 2000 estudiantes, la búsqueda de estudiantes no debe h...

7  Holding registros utilizando diccionario  ( Holding records using dictionary ) 
¿Puedes por favor ayudarme con el siguiente script? En este momento, el script está tomando hasta 20 minutos para ejecutar, dependiendo de la cantidad de da...

2  Tabla hash implementada por JavaScript  ( Hash table implemented by javascript ) 
Recientemente intenté implementar una tabla simple usando JavaScript. ¿Alguien podría ayudarme a revisar mi implementación? AssetClass6 En mi implement...

5  Finanzas familiares - seguimiento e informes  ( Family finances tracking and reporting ) 
Estoy buscando una forma limpia de acumular montos dentro de un conjunto de datos de entrada. En este ejemplo, hay 18 filas de datos, y la salida es de 3 fila...

5  Producto cartesiano de Python en un dictnario limitado  ( Python cartesian product in a constrained dictonary ) 
Quiero calcular el producto cartesiano de n Copias de una lista pequeña, 9988777665544331 . Quiero usar estas tites de productos cartesianos como llaves en...

4  Encuentra y reemplaza la optimización del método  ( String find and replace method optimization ) 
Estoy tratando de encontrar una cadena de encabezado específica de diferentes mapas ( 9988777665544330 , LEDES98BIheaders1 y LEDES98BI_V2headers ) En un e...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos