С++ Есть вектор кортежей типа
std::vector <tuple< ULONG, ULONG, ULONG, time_t, wstring, int >> drv;
std::vector <drvToTuple> drv;
сначала его сортирую
bool sortbyPath(const tuple<ULONG, ULONG, ULONG, time_t, wstring, int>& a,
const tuple<ULONG, ULONG, ULONG, time_t, wstring, int>& b)
{
return (get<4>(a) < get<4>(b));
}
sort(drv.begin(), drv.end(), sortbyPath);
Подскажите как удалить уникальные значения основываясь на 4 поле (wstring) кортежа?
2056, 2328, 94, 1545877351, L"Sasha", 15
2057, 2328, 94, 1545877351, L"Masha", 15
2057, 2328, 94, 1545877353, L"Dasha", 15
2058, 2328, 94, 1545877353, L"Sasha", 15
2059, 2328, 94, 1545877354, L"Misha", 15
2059, 2328, 94, 1545877354, L"Misha", 15
в итоге должно остаться
2056, 2328, 94, 1545877351, L"Sasha", 15
2057, 2328, 94, 1545877351, L"Masha", 15
2057, 2328, 94, 1545877353, L"Dasha", 15
2059, 2328, 94, 1545877354, L"Misha", 15
Вы можете использовать комбинацию метода вектора erase
со стандартным алгоритмом std::unique
. (Если вы хотите поместить результат в другой вектор или контейнер, то можно использовать алгоритм std::unique_copy
).
Например,
drv.erase( std::unique( std::begin( drv ), std::end( drv ),
[]( const auto &a, const auto &b )
{
return std::get<4>( a ) == std::get<4>( b );
} ), std::end( drv ) );
Ниже представлена демонстрационная программа
#include <iostream>
#include <iomanip>
#include <string>
#include <tuple>
#include <vector>
#include <iterator>
#include <algorithm>
#include <ctime>
typedef unsigned long ULONG;
int main()
{
std::vector<std::tuple<ULONG, ULONG, ULONG, time_t, std::wstring, int>> drv =
{
{ 056, 2328, 94, 1545877351, L"Sasha", 15 },
{ 2057, 2328, 94, 1545877351, L"Masha", 15 },
{ 2057, 2328, 94, 1545877353, L"Dasha", 15 },
{ 2058, 2328, 94, 1545877353, L"Sasha", 15 },
{ 2059, 2328, 94, 1545877354, L"Misha", 15 },
{ 2059, 2328, 94, 1545877354, L"Misha", 15 }
};
for ( const auto &item : drv )
{
std::wcout << std::setw( 4 ) << std::get<0>( item ) << ", "
<< std::setw( 4 ) << std::get<1>( item ) << ", "
<< std::setw( 2 ) << std::get<2>( item ) << ", "
<< std::get<3>( item ) << ". "
<< std::get<4>( item ) << ", "
<< std::get<5>( item ) << '\n';
}
std::wcout << '\n';
std::sort( std::begin( drv ),
std::end( drv ),
[]( const auto &a, const auto &b )
{
return std::get<4>( a ) < std::get<4>( b );
} );
drv.erase( std::unique( std::begin( drv ),
std::end( drv ),
[]( const auto &a, const auto &b )
{
return std::get<4>( a ) == std::get<4>( b );
} ), std::end( drv ) );
for ( const auto &item : drv )
{
std::wcout << std::setw( 4 ) << std::get<0>( item ) << ", "
<< std::setw( 4 ) << std::get<1>( item ) << ", "
<< std::setw( 2 ) << std::get<2>( item ) << ", "
<< std::get<3>( item ) << ". "
<< std::get<4>( item ) << ", "
<< std::get<5>( item ) << '\n';
}
return 0;
}
Ее вывод на консоль:
46, 2328, 94, 1545877351. Sasha, 15
2057, 2328, 94, 1545877351. Masha, 15
2057, 2328, 94, 1545877353. Dasha, 15
2058, 2328, 94, 1545877353. Sasha, 15
2059, 2328, 94, 1545877354. Misha, 15
2059, 2328, 94, 1545877354. Misha, 15
2057, 2328, 94, 1545877353. Dasha, 15
2057, 2328, 94, 1545877351. Masha, 15
2059, 2328, 94, 1545877354. Misha, 15
46, 2328, 94, 1545877351. Sasha, 15
С другой стороны, возможно вам сразу же следовало избрать другой контейнер, как, например, std::set
или std::unordered_set
.
Ниже представлена демонстрационная программа, которая показывает, как можно выбрать только уникальные элементы исходного вектора во множество std::set
без изменения самого вектора.
#include <iostream>
#include <iomanip>
#include <string>
#include <tuple>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>
#include <ctime>
typedef unsigned long ULONG;
int main()
{
std::vector<std::tuple<ULONG, ULONG, ULONG, time_t, std::wstring, int>> drv =
{
{ 056, 2328, 94, 1545877351, L"Sasha", 15 },
{ 2057, 2328, 94, 1545877351, L"Masha", 15 },
{ 2057, 2328, 94, 1545877353, L"Dasha", 15 },
{ 2058, 2328, 94, 1545877353, L"Sasha", 15 },
{ 2059, 2328, 94, 1545877354, L"Misha", 15 },
{ 2059, 2328, 94, 1545877354, L"Misha", 15 }
};
for ( const auto &item : drv )
{
std::wcout << std::setw( 4 ) << std::get<0>( item ) << ", "
<< std::setw( 4 ) << std::get<1>( item ) << ", "
<< std::setw( 2 ) << std::get<2>( item ) << ", "
<< std::get<3>( item ) << ". "
<< std::get<4>( item ) << ", "
<< std::get<5>( item ) << '\n';
}
std::wcout << '\n';
auto cmp = []( const auto &a, const auto &b )
{
return std::get<4>( a ) < std::get<4>( b );
};
std::set<std::tuple<ULONG, ULONG, ULONG, time_t, std::wstring, int>,
decltype( cmp )> tuple_set( cmp );
tuple_set.insert( std::begin( drv ), std::end( drv ) );
for ( const auto &item : tuple_set )
{
std::wcout << std::setw( 4 ) << std::get<0>( item ) << ", "
<< std::setw( 4 ) << std::get<1>( item ) << ", "
<< std::setw( 2 ) << std::get<2>( item ) << ", "
<< std::get<3>( item ) << ". "
<< std::get<4>( item ) << ", "
<< std::get<5>( item ) << '\n';
}
std::wcout << '\n';
return 0;
}
Вывод программы на консоль:
46, 2328, 94, 1545877351. Sasha, 15
2057, 2328, 94, 1545877351. Masha, 15
2057, 2328, 94, 1545877353. Dasha, 15
2058, 2328, 94, 1545877353. Sasha, 15
2059, 2328, 94, 1545877354. Misha, 15
2059, 2328, 94, 1545877354. Misha, 15
2057, 2328, 94, 1545877353. Dasha, 15
2057, 2328, 94, 1545877351. Masha, 15
2059, 2328, 94, 1545877354. Misha, 15
46, 2328, 94, 1545877351. Sasha, 15
Используйте std::unique()
и бинарный предикат, использующий вашу функцию sortbyPath()
:
template< class ExecutionPolicy, class ForwardIt, class BinaryPredicate >
ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, BinaryPredicate p );
код в итоге может быть примерно таким:
std::sort( drv.begin(), drv.end(), sortbyPath );
auto it = std::unique( drv.begin(), drv.end(), []( const auto &a, const auto &b ) {
return not sortbyPath( a, b ) and not sortByPath( b, a );
} );
drv.erase( it, drv.end() );
либо можно написать еще одну функцию equalByPath()
, что породит дублирование кода, но будет скорее всего более эффективным.
Если вы сортируете только для того, чтобы оставить уникальные, то это делать не обязательно, проще использовать std::unordered_set
и std::remove_if
:
std::unordered_set<std::wstring> uset; // тут была ошибка unoredered_set вместо unordered_set
auto it = std::remove_if( drv.begin(), drv.end(), [&uset]( const auto &d ) {
return not uset.insert( std::get<4>( d ) ).second;
} );
drv.erase( it, drv.end() );
Виртуальный выделенный сервер (VDS) становится отличным выбором
Почему в следующем коде нет ошибок компиляции, но clang-tidy выдаёт ошибку? Компилирую с помощью gcc
Возник такой вопрос: у меня есть главный класс Figures, от которого я унаследовал Circle,Square,Triangle и тд
Начал писать свой оптимизатор-транслятор кода for funЯ новичок в c++ и ЯВУ
У меня есть проект, который содержит в себе два других (использую subdirs)Вызовом нужных функций из подпроектов занимается класс MainWindow, который...