条件打印和计数超过 std::map 有限制
Conditional printing and counting over std::map with restrictions
我目前正在学习 C++17,在练习使用标准库以习惯使用这些功能的过程中,我们遇到了挑战:
- 迭代
std::map<std::string, size_t>
(也称为 std::map<file_name, file_size>
)
- 打印空文件名
size_t == 0
和 return 计数
- 打印不为空的文件名
size_t != 0
和 return 计数
- 正在从地图中删除
std::pairs
whose size_t == 0
限制:
只能使用headers: <vector>
, <map>
, <string>
, <algorithm>
, <functional>
不能定义复杂类型和模板
无法使用 . (member access), -> (member access via pointer), * (dereference) operators
不能使用for, while, do-while nor if-else, switch
和其他条件
可以使用std::for_each
和函数模板的其他函数迭代collection个元素
没有 lambdas
无std::cout
、std::cerr
、std::ostream
等
没有自动类型
可以使用其他功能,只要它们包含在限制 #1
中描述的 headers 中
允许使用这些功能:
void print(const std::string& str)
{
std::cout << str << std::endl;
}
std::string split(const std::pair<std::string, size_t> &r)
{
std::string name;
std::tie(name, std::ignore) = r;
return name;
}
bool checkEmpty(const std::pair<std::string, size_t>& r, bool trueIfIsNot
)
{
file_size size;
std::tie(std::ignore, size) = r;
bool result = (size == 0);
if (trueIfIsNot)
{
result = !result;
}
return result;
}
我开始欣赏在我之前的 post 中使用 std::bind
和 std::for_each
。这一次,我如何添加谓词和条件来修改输出而不使用限制 #4 规定的语法?
我目前正在考虑使用 std::transform()
或 std::copy_if()
等。我对标准库的许多功能有一些了解,但我认为我在语法方面非常薄弱,无法理解其工作原理在一起所以我不知道如何使用它们。
您可以完成 2,3 项任务:
- 使用
vector
初始大小作为地图大小
- 使用
copy_if
根据条件从地图复制元素
- 使用
for_each
有界 split
/print
- return 项目数作为向量中第一项和最后一项之间的差异
代码:
int task2and3(const std::map<std::string,int>& m, bool trueIfIsNot)
{
std::vector<std::pair<std::string,int>> vec(m.size());
auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),
std::bind(checkEmpty,std::placeholders::_1,trueIfIsNot));
std::for_each(vec.begin(), firstPastEnd,
std::bind(print,std::bind(split,std::placeholders::_1)));
return firstPastEnd - vec.begin();
}
通过 trueIfIsNot
指示打印了哪些对(值为 0 或其他)。
要完成第 4 个任务,您还可以使用 vector
来存储 map
的项目。要从地图中删除元素,您可以在向量中迭代这些项目(使用 for_each
)并调用 map::erase
方法。因为这个函数成员有重载,所以你需要正确地转换它以指示方法通过 key_type
删除元素。使用 split
从对中得到这个 key_type
。
void task4(std::map<std::string,int>& m)
{
std::vector<std::pair<std::string,int>> vec(m.size());
auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),std::bind(checkEmpty,std::placeholders::_1,false));
using sizeType = std::map<std::string,int>::size_type;
using keyType = std::map<std::string,int>::key_type;
for_each(vec.begin(), firstPastEnd,
std::bind( static_cast<sizeType (std::map<std::string,int>::*)(const keyType&) >(&std::map<std::string,int>::erase),
&m,
std::bind(split,std::placeholders::_1)) );
}
我目前正在学习 C++17,在练习使用标准库以习惯使用这些功能的过程中,我们遇到了挑战:
- 迭代
std::map<std::string, size_t>
(也称为std::map<file_name, file_size>
) - 打印空文件名
size_t == 0
和 return 计数 - 打印不为空的文件名
size_t != 0
和 return 计数 - 正在从地图中删除
std::pairs
whose size_t == 0
限制:
只能使用headers:
<vector>
,<map>
,<string>
,<algorithm>
,<functional>
不能定义复杂类型和模板
无法使用
. (member access), -> (member access via pointer), * (dereference) operators
不能使用
for, while, do-while nor if-else, switch
和其他条件可以使用
std::for_each
和函数模板的其他函数迭代collection个元素没有 lambdas
无
std::cout
、std::cerr
、std::ostream
等没有自动类型
可以使用其他功能,只要它们包含在限制 #1
中描述的 headers 中
允许使用这些功能:
void print(const std::string& str)
{
std::cout << str << std::endl;
}
std::string split(const std::pair<std::string, size_t> &r)
{
std::string name;
std::tie(name, std::ignore) = r;
return name;
}
bool checkEmpty(const std::pair<std::string, size_t>& r, bool trueIfIsNot
)
{
file_size size;
std::tie(std::ignore, size) = r;
bool result = (size == 0);
if (trueIfIsNot)
{
result = !result;
}
return result;
}
我开始欣赏在我之前的 post 中使用 std::bind
和 std::for_each
。这一次,我如何添加谓词和条件来修改输出而不使用限制 #4 规定的语法?
我目前正在考虑使用 std::transform()
或 std::copy_if()
等。我对标准库的许多功能有一些了解,但我认为我在语法方面非常薄弱,无法理解其工作原理在一起所以我不知道如何使用它们。
您可以完成 2,3 项任务:
- 使用
vector
初始大小作为地图大小 - 使用
copy_if
根据条件从地图复制元素 - 使用
for_each
有界split
/print
- return 项目数作为向量中第一项和最后一项之间的差异
代码:
int task2and3(const std::map<std::string,int>& m, bool trueIfIsNot)
{
std::vector<std::pair<std::string,int>> vec(m.size());
auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),
std::bind(checkEmpty,std::placeholders::_1,trueIfIsNot));
std::for_each(vec.begin(), firstPastEnd,
std::bind(print,std::bind(split,std::placeholders::_1)));
return firstPastEnd - vec.begin();
}
通过 trueIfIsNot
指示打印了哪些对(值为 0 或其他)。
要完成第 4 个任务,您还可以使用 vector
来存储 map
的项目。要从地图中删除元素,您可以在向量中迭代这些项目(使用 for_each
)并调用 map::erase
方法。因为这个函数成员有重载,所以你需要正确地转换它以指示方法通过 key_type
删除元素。使用 split
从对中得到这个 key_type
。
void task4(std::map<std::string,int>& m)
{
std::vector<std::pair<std::string,int>> vec(m.size());
auto firstPastEnd = std::copy_if(m.begin(),m.end(),vec.begin(),std::bind(checkEmpty,std::placeholders::_1,false));
using sizeType = std::map<std::string,int>::size_type;
using keyType = std::map<std::string,int>::key_type;
for_each(vec.begin(), firstPastEnd,
std::bind( static_cast<sizeType (std::map<std::string,int>::*)(const keyType&) >(&std::map<std::string,int>::erase),
&m,
std::bind(split,std::placeholders::_1)) );
}