С++ Есть вектор кортежей типа
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() );
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости