我尝试将以下字符串列表洗牌:

list<string> l({"10000007", "1", "4", "5", "7", "12", "23", "25", "26", "27", "30", "31", "32", "44", "46", "47", "59", "65", "91"})
我所有的尝试都失败了。这是我最好的尝试之一。
尝试1
基本上我从这个回答的Randomize a std::list<std::string>复制
#include <iostream>
#include <functional>
#include <iterator>
#include <algorithm>
#include <string>
#include <list>
#include <vector>
#include <random>
#include <numeric>

int main() {
    std::list<std::string> l({"10000007", "1", "4", "5", "7", "12", "23", "25", "26", "27", "30", "31", "32", "44", "46", "47", "59", "65", "91"});
    std::vector<std::reference_wrapper<std::string>> v(l.cbegin(), l.cend());
    std::random_device rd;
    std::mt19937 generator(rd());
    std::shuffle(v.begin(), v.end(), generator);
    std::cout << "Original list:\n";
    std::copy(l.cbegin(), l.cend(), std::ostream_iterator<std::string>(std::cout, " "));
    std::cout << "\nShuffled view:\n";
    std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
}
我有此错误跟踪:
In file included from /usr/include/c++/7/vector:62:0,
                 from /usr/include/c++/7/functional:61,
                 from prueba.cpp:2:
/usr/include/c++/7/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = std::reference_wrapper<std::__cxx11::basic_string<char> >; _Args = {const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]’:
/usr/include/c++/7/bits/stl_uninitialized.h:83:18:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; _ForwardIterator = std::reference_wrapper<std::__cxx11::basic_string<char> >*; bool _TrivialValueTypes = false]’
/usr/include/c++/7/bits/stl_uninitialized.h:134:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; _ForwardIterator = std::reference_wrapper<std::__cxx11::basic_string<char> >*]’
/usr/include/c++/7/bits/stl_uninitialized.h:289:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; _ForwardIterator = std::reference_wrapper<std::__cxx11::basic_string<char> >*; _Tp = std::reference_wrapper<std::__cxx11::basic_string<char> >]’
/usr/include/c++/7/bits/stl_vector.h:1331:33:   required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; _Tp = std::reference_wrapper<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::reference_wrapper<std::__cxx11::basic_string<char> > >]’
/usr/include/c++/7/bits/stl_vector.h:1299:23:   required from ‘void std::vector<_Tp, _Alloc>::_M_initialize_dispatch(_InputIterator, _InputIterator, std::__false_type) [with _InputIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; _Tp = std::reference_wrapper<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::reference_wrapper<std::__cxx11::basic_string<char> > >]’
/usr/include/c++/7/bits/stl_vector.h:414:26:   required from ‘std::vector<_Tp, _Alloc>::vector(_InputIterator, _InputIterator, const allocator_type&) [with _InputIterator = std::_List_const_iterator<std::__cxx11::basic_string<char> >; <template-parameter-2-2> = void; _Tp = std::reference_wrapper<std::__cxx11::basic_string<char> >; _Alloc = std::allocator<std::reference_wrapper<std::__cxx11::basic_string<char> > >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::reference_wrapper<std::__cxx11::basic_string<char> > >]’
prueba.cpp:13:76:   required from here
/usr/include/c++/7/bits/stl_construct.h:75:7: error: binding reference of type ‘std::__cxx11::basic_string<char>&’ to ‘const std::__cxx11::basic_string<char>’ discards qualifiers
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/std_function.h:44:0,
                 from /usr/include/c++/7/functional:58,
                 from prueba.cpp:2:
/usr/include/c++/7/bits/refwrap.h:334:7: note:   initializing argument 1 of ‘std::reference_wrapper<_Tp>::reference_wrapper(_Tp&) [with _Tp = std::__cxx11::basic_string<char>]’
       reference_wrapper(_Tp& __indata) noexcept
       ^~~~~~~~~~~~~~~~~
我试图了解 reference_wrapper 在此示例中的操作,但没有成功。
其他尝试
我对经典组合的所有尝试也都失败了...使用random_engineshufflesrand时,跟踪错误有数千行。
为什么不转换为整数?
在我的原始代码中,有两个.json文件,而jsons始终具有字符串格式的密钥。我知道我可以将字符串列表转换为整数列表,但是问题是我正在创建算法,并且有:
  • 2000列出
  • 算法中的
  • 2000次迭代
  • 您必须在每次迭代中多次执行此转换 (字符串到int,从int到字符串...)

  • 因此,我认为此选项在计算上会非常昂贵。
    提前致谢。

    最佳答案

    我首先要质疑使用std::list的用途/需求。在这种情况下,您似乎只在使用list初始化vector。在这种情况下,您最好直接初始化并直接使用vector:

    #include <iostream>
    #include <functional>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <list>
    #include <vector>
    #include <random>
    #include <numeric>
    
    int main() {
        std::vector<std::string> v({"10000007", "1", "4", "5", "7", "12", "23", "25", "26", "27", "30", "31", "32", "44", "46", "47", "59", "65", "91"});
        std::random_device rd;
    
        std::cout << "Original list:\n";
        std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
    
        std::mt19937 generator(rd());
        std::shuffle(v.begin(), v.end(), generator);
    
        std::cout << "\nShuffled view:\n";
        std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
    
        std::cout << "\n";
    }
    
    如果您仍然坚持使用列表,则可以摆脱引用包装,它将起作用:
    #include <iostream>
    #include <functional>
    #include <iterator>
    #include <algorithm>
    #include <string>
    #include <list>
    #include <vector>
    #include <random>
    #include <numeric>
    
    int main() {
        std::list<std::string> l({"10000007", "1", "4", "5", "7", "12", "23", "25", "26", "27", "30", "31", "32", "44", "46", "47", "59", "65", "91"});
        std::vector<std::string> v(l.cbegin(), l.cend());
        std::random_device rd;
        std::mt19937 generator(rd());
        std::shuffle(v.begin(), v.end(), generator);
        std::cout << "Original list:\n";
        std::copy(l.cbegin(), l.cend(), std::ostream_iterator<std::string>(std::cout, " "));
        std::cout << "\nShuffled view:\n";
        std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
    }
    
    ...但是我对此没有多大意义。
    至于存储整数和字符串的开销:只要您使用的是相对较新的编译器,那么它的(库)std::string实现就具有短字符串优化功能,两者之间可能并没有太大的区别。如果(可能)需要支持缺少短字符串优化的较旧的编译器,则可以大大增加转换和存储int而不是存储字符串的机会。
    问题非常简单:如果没有短字符串优化,则每个字符串都会导致堆分配以存储实际数据。该堆分配可能很容易比与int之间的转换慢(但您需要进行测试以确保确定)。
    对于那些非常关心速度的人,理想的选择可能是将整个json文件存储到内存中,然后为您关心的值创建string_view对象。然后,您可以随机播放string_view对象,并根据需要将它们打印出来(或其他方式),但是所有这些对象都只包含指向原始数据的指针,因此您无需复制所有底层数据。

    10-07 12:51
    查看更多