这是从代码审查到我的任务.我想根据一种特殊的比较谓词从一个集合中选择一个最小值.喜欢这个:
struct Complex { ... };

float calcReduction(Complex elem);

Complex findMinValueWithPredicates(const std::vector<Complex>& values)
{
  auto it = std::min_element(values.begin(),values.end(),[](const Complex& a,const Complex& b) { 
                               return calcReduction(a) < calcReduction(b); 
                             });

  if (it == values.end()) throw std::runtime_error("");

  return *it;
}

这里我找到基于谓词的最小元素.该谓词计算两个值的缩小以浮动,然后比较这些浮点数.工作正常,看起来整齐.

你能看到问题吗?是的,对于一组N个元素calcReduction()被称为2N次,而它只需要计算N次,每次为每个元素一次.

解决这个问题的一个原因是写出明确的计算:

Complex findMinValueExplicit(const std::vector<Complex>& values)
{
  float minReduction = std::numeric_limits<float>::max();
  Complex minValue;

  for (Complex value : values)
  {
    float reduction = calcReduction(value);
    if (reduction < minReduction)
    {
      minReduction = reduction;
      minValue = value;
    }
  }

  if (minReduction == std::numeric_limits<float>::max()) throw std::runtime_error("");

  return minValue;
}

它工作正常,我们只有N个调用calcReduction().但是,与明确调用min_element相比,它看起来太冗长,并且意图不是那么清楚.因为当你调用min_element时,很容易猜到你要找到一个最小的元素,你知道.

我现在唯一的想法是创建我自己的算法,如min_element_with_reduction,接受范围和缩小功能.听起来很合理,但我不知道是否有任何现成的解决方案.

任何想法如何解决这个任务明确的意图和一些现成的解决方案? Boost受欢迎. C 17和范围很有趣.

解决方法

您可以使用boost :: range library.
auto reductionLambda = [](const Complex& a) { return calcReduction(a); };
auto it = boost::range::min_element(values | boost::adaptors::transformed( 
                             std::ref(reductionLambda));

范围本身也应该与C 17达到标准C.

编辑

正如我们在评论中所看到的,这也会使转换两次.

所以这里有一些乐趣:

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/assign.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>


template <class Iterator,class UnaryFunction>
class memoizing_transform_iterator
  : public boost::iterator_adaptor<
        memoizing_transform_iterator<Iterator,UnaryFunction> // Derived,Iterator                                              // Base,std::decay_t<decltype(std::declval<UnaryFunction>()(std::declval<typename Iterator::value_type>()))> // Value,boost::forward_traversal_tag    // CategoryOrTraversal
    >
{
 public:
    memoizing_transform_iterator() {}

    explicit memoizing_transform_iterator(Iterator iter,UnaryFunction f)
      : memoizing_transform_iterator::iterator_adaptor_(iter),fun(f) {}

    static int total;
 private:
    friend class boost::iterator_core_access;
    void increment() { ++this->base_reference(); memoized = false; }

    using MemoType = std::decay_t<decltype(std::declval<UnaryFunction>()(std::declval<typename Iterator::value_type>()))>;      

    MemoType& dereference() const 
    {
        if (!memoized) {
            ++total;
            memoized = true;
            memo = fun(*this->base());
        }
        return memo;
    }

    UnaryFunction fun;
    mutable bool memoized = false;
    mutable MemoType memo;
};


template <class Iterator,class UnaryFunction>
auto make_memoizing_transform_iterator(Iterator i,UnaryFunction&& f)
{
    return memoizing_transform_iterator<Iterator,UnaryFunction>(i,f);
}



template<class I,class U>
int memoizing_transform_iterator<I,U>::total = 0;


// THIS IS copIED FROM LIBSTDC++
template<typename _ForwardIterator>
   _ForwardIterator
     min_el(_ForwardIterator __first,_ForwardIterator __last)
     {
       if (__first == __last)
     return __first;
       _ForwardIterator __result = __first;
       while (++__first != __last)
     if (*__first < *__result)
       __result = __first;
       return __result;
     }


int main(int argc,const char* argv[])
{
    using namespace boost::assign;

    std::vector<int> input;
    input += 2,3,4,1,5,6,7,8,9,10;


    auto transformlambda = [](const int& a) { return a*2; };


    auto begin_it = make_memoizing_transform_iterator(input.begin(),std::ref(transformlambda));
    auto end_it = make_memoizing_transform_iterator(input.end(),std::ref(transformlambda));
    std::cout << *min_el(begin_it,end_it).base() << "\n";

    std::cout <<begin_it.total;

    return 0;
}

基本上我实现了一个迭代器来记录调用变换函数的结果.奇怪的是,至少在在线编译器中,迭代器在被取消引用的值被比较之前被复制(从而击败了记忆的目的).但是当我简单地从libstdc复制实现时,它的工作原理如下.也许你可以在真实的机器上尝试一下?实例是here.

小编:我在VS2015测试,它的工作原理与std :: min_element.

c – 根据变换的值查找最小元素的更多相关文章

  1. HTML实现代码雨源码及效果示例

    这篇文章主要介绍了HTML实现代码雨源码及效果示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 吃透移动端 1px的具体用法

    这篇文章主要介绍了吃透移动端 1px的具体用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. html5开发三八女王节表白神器

    一年一度的三八女王节马上来临,今天小编基于html5给大家开发一个表白神器,做一个 浪漫的程序猿,具体代码大家参考下本文

  4. html5实现图片转圈的动画效果——让页面动起来

    这篇文章主要介绍了html5实现图片转圈的动画效果——让页面动起来的相关资料,需要的朋友可以参考下

  5. HTML5 3D书本翻页动画的实现示例

    这是一款十分炫酷的HTML5 3D书本翻页动画,效果相对比较简单,拖拽鼠标模拟用手翻页,需要的朋友们下面随着小编来一起学习学习吧

  6. html5简介及新增功能介绍

    这篇文章主要介绍了html5简介及新增功能介绍,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. HTML5 图片悬停放大的实现代码示例

    这篇文章主要介绍了HTML5 图片悬停放大的实现代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. ios – 相机图像旋转问题

    我在这里遇到一个非常奇怪的问题.当我以纵向模式单击图像并上传它然后再次获取它时,显示逆时针旋转90度.但是当我在相机胶卷中看到它时,它会以正确的方向显示.我已经尝试了几乎所有可能的链接/代码来解决这个问题,但似乎没有任何帮助.我以JPEG格式保存图像.请帮助这个人.提前致谢!!解决方法解决方法是在UIImage上创建一个类别,并根据其元数据EXIF缩放和旋转图像.这是一段神奇的代码:

  9. 如何在iOS上生成带有“真实”文本内容的PDF?

    我想在iOS6应用程序中生成一个好看的PDF.我试过了:>UIView在上下文中渲染>使用CoreText>使用NsstringdrawInRect>使用UILabeldrawRect这是一个代码示例:呈现的UIViews只包含UIImageView一堆UILabel.我还尝试了在stackoverflow上找到的建议:继承UILabel并执行此操作:但这也没有改变任何事情.无论我做什么,当在预览中打开PDF时,文本部分可以选择作为块,但不是每个字符的字符,并且缩放pdf显示它实际上是位图图像.有什么建议

  10. 内存警告UIImagepickerController IOS 7

    任何人都可以帮助我解决这个问题,我对客观的c和iOS有点新鲜.我一直在努力,但我无法弄清楚如何解决问题,我的应用程序非常简单,只有启动相机拍照并通过电子邮件发送到我们的服务器.这个代码在iOS6中工作得很好.当我拍照时,我的内存是每个屏幕捕获的堆增长,我得到“收到内存警告”,最后–由于内存压力而终止.–可能是内存管理.我会感谢你的帮助解决方法您使用fixRotation方法处于正确的轨道.但是,您

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&amp;GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部