извлекать значения из карты с одинаковыми данными [duplicate]

Чтение коллекции с клиентами и сохранение в файл с помощью JFilechooser.

private void writeFile(){

    JFileChooser fileChooser = new JFileChooser(this.PATH);
    int retValue = fileChooser.showDialog(this, "Save File");

    if (retValue == JFileChooser.APPROVE_OPTION){

        try (Writer fileWrite = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileChooser.getSelectedFile())))){

            this.customers.forEach((c) ->{
                try{
                    fileWrite.append(c.toString()).append("\n");
                }
                catch (IOException ex){
                    ex.printStackTrace();
                }
            });
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }
}
27
задан Eric 24 July 2012 в 16:56
поделиться

9 ответов

Вы можете использовать boost :: multi_index для создания двунаправленной карты - вы можете использовать либо значение пары в качестве ключа для быстрого поиска.

19
ответ дан Mark Ransom 21 August 2018 в 20:02
поделиться

Как насчет использования другой карты внутри, которая хранит значение, комбинацию клавиш.

Да: поддерживайте две карты, одна карта использует один тип ключа, а другой - другой.

Нет, это двоичный поиск отсортированного дерева: его скорость равна O (log (n)).

14
ответ дан ChrisW 21 August 2018 в 20:02
поделиться
  • 1
    В этом есть смысл. Таким образом, сохранение двух карт даст хорошую производительность, чем последовательный поиск и поиск ценности, не так ли? – Navaneeth K N 11 February 2009 в 04:57
  • 2
    Это займет в два раза больше времени, чтобы вставить или удалить что-либо (используя две карты вместо одного); но для большого количества элементов поиск будет намного быстрее, потому что O (log (n)) намного меньше, чем O (n), который необходим для последовательного поиска. – ChrisW 11 February 2009 в 05:03
  • 3
    Великий Крис. Благодарю. – Navaneeth K N 11 February 2009 в 05:05
  • 4
    Так просто, но так хорошо (особенно при использовании библиотеки boost не является вариантом). Имейте мой upvote. Я хотел бы добавить, что использование std::multimap, вероятно, лучше, чем std::map для перевернутой карты, потому что ваша исходная карта может иметь повторяющиеся значения. Эти повторяющиеся значения становятся ключами на карте, поэтому использование std::map приведет к потере данных. – Dennis 5 September 2011 в 07:15

Если у вас есть доступ к отличной библиотеке boost , вы должны использовать boost :: multi_index , чтобы создать двунаправленную карту , как говорит Марк. В отличие от std :: map это позволяет вам искать либо ключ, либо значение.

Если у вас есть только STL, чтобы передать следующий код, он выполнит трюк (шаблонный для работы с любым типом map, где mapped_type поддерживает оператор ==):

#include <map>
#include <string>
#include <algorithm>
#include <iostream>
#include <cassert>

template<class T>
struct map_data_compare : public std::binary_function<typename T::value_type, 
                                                      typename T::mapped_type, 
                                                      bool>
{
public:
    bool operator() (typename T::value_type &pair, 
                     typename T::mapped_type i) const
    {
        return pair.second == i;
    }
};


int main()
{
    typedef std::map<std::string, int> mapType;

    mapType map;

    map["a"] = 1;
    map["b"] = 2;
    map["c"] = 3;
    map["d"] = 4;
    map["e"] = 5;

    const int value = 3;

    std::map<std::string, int>::iterator it = std::find_if( map.begin(), map.end(), std::bind2nd(map_data_compare<mapType>(), value) );

    if ( it != map.end() )
    {
        assert( value == it->second);
        std::cout << "Found index:" << it->first << " for value:" << it->second << std::endl;
    }
    else
    {
        std::cout << "Did not find index for value:" << value << std::endl;
    }
}
15
ответ дан CodeBuddy 21 August 2018 в 20:02
поделиться

Посмотрите на двунаправленные карты boost: http://www.boost.org/doc/libs/1_38_0/libs/bimap/doc/html/index.html

Он позволяет обеим значениям действовать как ключ.

В противном случае итерация - это путь.

6
ответ дан Evan Teran 21 August 2018 в 20:02
поделиться

Нет, вам нужно перебрать std :: map и проверить все значения вручную. В зависимости от того, что вы хотите сделать, вы можете перенести std :: map в простой класс, который также кэширует все значения, которые вставляются в карту, в то, что легко найти и не позволяет дублировать, например, std ::задавать. Не наследуйте от std :: map (у него нет виртуального деструктора!), Но оберните его, чтобы вы могли сделать что-то вроде этого:

WrappedMap my_map< std::string, double >;
my_map[ "key" ] = 99.0;
std::set< double > values = my_map.values(); // should give back a set with only 99.0 in it

Альтернативой катите было бы использовать двунаправленную карту Boost, которую можно легко найти в сообщениях ниже или Google.

Это действительно зависит от того, что вы хотите делать, как часто вы хотите это сделать и насколько сложно это сделать состоит в том, чтобы свернуть собственный небольшой класс-оболочку против установки и использования Boost. Мне нравится Boost, так что это хороший способ - но есть что-то приятное и полное в создании собственного класса обертки. У вас есть преимущество в том, что вы понимаете непосредственно сложность операций, и вам может не понадобиться полное обратное отображение значений => ключей, которые предоставляются двунаправленной картой Boost.

2
ответ дан James Thompson 21 August 2018 в 20:02
поделиться
  • 1
    Ему нужен итератор для элемента, поэтому вы хотите использовать вторую карту & lt; gt; а не множество & gt ;. – j_random_hacker 11 February 2009 в 05:01

попробуйте эту функцию:

template <class Map, class Val> typename Map::const_iterator MapSearchByValue(const Map & SearchMap, const Val & SearchVal)
{
    Map::const_iterator iRet = SearchMap.end();
    for (Map::const_iterator iTer = SearchMap.begin(); iTer != SearchMap.end(); iTer ++)
    {
        if (iTer->second == SearchVal)
        {
            iRet = iTer;
            break;
        }
    }
    return iRet;
}

Я думаю, что это полезно

4
ответ дан Mitch 21 August 2018 в 20:02
поделиться
  • 1
    Исправьте меня, если я ошибаюсь, но разве это не просто код в вопросе? – Jonathan Mee 9 December 2015 в 21:35
  • 2
    @JonathanMee Вы не ошибаетесь. – Josh C 29 December 2015 в 16:58

Возможно, я не совсем понимаю, чего вы пытаетесь выполнить. Но чтобы просто проверить, содержит ли карта значение, я считаю, что вы можете использовать std::map в find.

bool ContainsValue(Type_ value)
{
    return (internalMap.find(value) != internalMap.end());
}
-3
ответ дан Ternary 21 August 2018 в 20:02
поделиться
  • 1
    std::map::find выполняет поиск по ключу, он пытается выполнить поиск по значению. – Dennis 5 September 2011 в 07:12
  • 2
    Вы абсолютно правы. Я предполагаю, что вам не нужно повторять и искать карту вручную, вы должны использовать двунаправленную карту, такую ​​как уже предложенный Boost.MultiIndex. – Ternary 16 September 2011 в 16:38

Не самый лучший вариант, но может быть полезен в немногих случаях, когда пользователь присваивает значение по умолчанию, например 0 или NULL, при инициализации.

Ex.
< int , string >
< string , int > 
< string , string > 

consider < string , string >
mymap["1st"]="first";
mymap["second"]="";
for (std::map<string,string>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
{
       if ( it->second =="" ) 
            continue;
}
0
ответ дан user2761565 21 August 2018 в 20:02
поделиться

То, что вы запрашиваете, именно то, что делает std :: find (не функция-член)

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );
0
ответ дан Vaidas 21 August 2018 в 20:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: