IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 函数式编程(一)查询容器内元素 -> 正文阅读

[数据结构与算法]函数式编程(一)查询容器内元素

函数式编程(一)查询容器内元素

参照《函数式编程C++》这本书内容,同时很推荐该书,要有c++17及以上的基础。

总体来说,就是讲解如何通过函数方式,实现查询容器内元素的功能。

首先,可以通过输入filterfunction,查询到容器内符合filter条件的容器元素。

template <typename FilterFunction>  // 定义filter模板
std::vector<std::string> names_for(
		const std::vector<person_t> &people,
		FilterFunction filter)
{
	std::vector<std::string> result;

	for (const person_t& person: people) {  // 循环遍历符合条件的元素
		if (filter(person)) {
			result.push_back(name(person));
		}
	}

	return result; // 返回结果容器
}

然而,这种操作必然会产生内存的消耗,过程中拷贝复制,需要优化。

于是,采用了一个递归调用的方式来实现。

template <typename T>
T tail(const T &collection) {  
    return T(collection.cbegin() + 1, collection.cend());  // 返回容器下一个元素
}
template <typename T, typename C>
C prepend(T &&item, C collection) {
    C result(collection.size() + 1);
    result[0] = std::forward<T>(item);  // 右值转移
    std::copy(collection.cbegin(), collection.cend(), result.begin() + 1);
    return result;
}
template <typename FilterFunction>  // 定义filter模板
std::vector<std::string> names_for(
        const std::vector<person_t> &people,
        FilterFunction filter)
{
    if (people.empty()) {
        return {};

    } else {
        const auto head = people.front();
        const auto processed_tail = names_for(  // 递归调用,tail为移动到容器下一个元素
                tail(people),
                filter);

        if (filter(head)) {
            return prepend(name(head), processed_tail); // prepend,将元素插入到结果容器中
        } else {
            return processed_tail; 
        }
    }
}

然而,这种递归在其函数的调用开销会很大,在容器体量较大时,有堆栈溢出的风险,

于是,采用尾递归调用方式,即递归后不做任何处理,将中间需要创建结果容器的步骤移除。

template <typename FilterFunction, typename Iterator>  // 定义filter模板
std::vector<std::string> names_for_helper(
        Iterator people_begin,
        Iterator people_end,
        FilterFunction filter,
        std::vector<std::string> previously_collected)  // 追加了结果集参数,这样不需要每次获取结果集
{
    if (people_begin == people_end) {	// 递归结束
        return previously_collected;
    } else {
        const auto head = *people_begin;
        if (filter(head)) {
            previously_collected.push_back(name(head));
            
        }
		return names_for_helper(	// 直接操作容器
                    people_begin + 1,
                    people_end,
                    filter,
                    previously_collected);
    }
}

附:

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <fstream>
#include <algorithm>
#include <iterator>

#include "person.h"

//#define USE_RECURSIVE_IMPLEMENTATION
#define USE_TAIL_RECURSIVE_IMPLEMENTATION

std::string name(const person_t &person)
{
    return person.name();
}

bool is_female(const person_t &person)
{
    return person.gender() == person_t::female;
}

bool is_not_female(const person_t &person)
{
    return !is_female(person);
}

template <typename T>
T tail(const T &collection)
{
    return T(collection.cbegin() + 1, collection.cend());
}

template <typename T, typename C>
C prepend(T &&item, C collection)
{
    C result(collection.size() + 1);
    result[0] = std::forward<T>(item);
    std::copy(collection.cbegin(), collection.cend(), result.begin() + 1);
    return result;
}

#ifdef USE_RECURSIVE_IMPLEMENTATION
template <typename FilterFunction>
std::vector<std::string> names_for(
        const std::vector<person_t> &people,
        FilterFunction filter)
{
    if (people.empty()) {
        return {};

    } else {
        const auto head = people.front();
        const auto processed_tail = names_for(
                tail(people),
                filter);

        if (filter(head)) {
            return prepend(name(head), processed_tail);
        } else {
            return processed_tail;
        }
    }
}
#else
template <typename FilterFunction>
std::vector<std::string> names_for(
		const std::vector<person_t> &people,
		FilterFunction filter)
{
	std::vector<std::string> result;

	for (const person_t& person: people) {
		if (filter(person)) {
			result.push_back(name(person));
		}
	}

	return result;
}
#endif

#ifdef USE_TAIL_RECURSIVE_IMPLEMENTATION
template <typename FilterFunction, typename Iterator>
std::vector<std::string> names_for_helper(
        Iterator people_begin,
        Iterator people_end,
        FilterFunction filter,
        std::vector<std::string> previously_collected)
{
    if (people_begin == people_end) {
        return previously_collected;

    } else {
        const auto head = *people_begin;

        if (filter(head)) {
            previously_collected.push_back(name(head));
            
        }
		return names_for_helper(
                    people_begin + 1,
                    people_end,
                    filter,
                    previously_collected);

    }
}

template <typename FilterFunction, typename Iterator>
std::vector<std::string> names_for(
        Iterator people_begin,
        Iterator people_end,
        FilterFunction filter)
{
        return names_for_helper(people_begin,
                                people_end,
                                filter,
                                {});
}
#endif

int main(int argc, char *argv[])
{
	std::cout << "Hello world!" << std::endl;
	    std::vector<person_t> people {
        { "David"  , person_t::male   },
        { "Jane"   , person_t::female },
        { "Martha" , person_t::female },
        { "Peter"  , person_t::male   },
        { "Rose"   , person_t::female },
        { "Tom"    , person_t::male   }
    };
#ifdef USE_TAIL_RECURSIVE_IMPLEMENTATION
	auto names = names_for(people.begin(), people.end(), is_female);
#else
	auto names = names_for(people, is_female);
#endif
    
    for (const auto& name: names) {
        std::cout << name << '\n';
    }

	return 0;
} 
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:50:35  更:2022-03-30 18:53:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:55:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码