代码之家  ›  专栏  ›  技术社区  ›  James Thompson

命令式语言中的类SQL选择

  •  2
  • James Thompson  · 技术社区  · 17 年前

    我在工作中用C++做一些编码,我做的很多事情都涉及分析数据集。我经常需要从STL容器中选择一些元素,我经常写这样的代码:

    using std::vector;
    vector< int > numbers;
    for ( int i = -10; i <= 10; ++i ) {
        numbers.push_back( i );
    }
    
    vector< int > positive_numbers;
    for ( vector< int >::const_iterator it = numbers.begin(), end = numbers.end();
            it != end; ++it 
    ) {
        if ( number > 0 ) {
            positive_numbers.push_back( *it );
        }
    }
    

    SELECT * INTO positive_numbers FROM numbers WHERE num > 0
    

    7 回复  |  直到 13 年前
        1
  •  2
  •   Stack Overflow is garbage    17 年前

    你几乎完全描述了 LINQ 这是一个。NET 3.5特性,因此您应该能够从C++使用它。

        2
  •  4
  •   Matt Bridges    17 年前

    您所描述的功能通常出现在支持闭包、谓词、functor等概念的函数式语言中。

    上面代码的问题在于它结合了:

    1. 将元素从一个集合复制到另一个集合的逻辑

    实际上,(1)和(3)是样板,因为每次你需要迭代一个集合,将一些元素复制到另一个集合时,每次可能只有条件代码会改变。支持函数式编程的语言消除了这种样板。例如,在Groovy中,您可以将上面的For循环替换为

    def positive_numbers = numbers.findAll{it > 0}
    

    尽管C++不是函数式语言,但可能有一些库支持使用STL集合进行函数式编程。例如,Apache commons集合(也可能是谷歌的集合库)为Java集合的函数式编程提供了支持,尽管Java本身不是函数式语言。

        3
  •  4
  •   Dónal    17 年前

    我想你已经描述过了 LINQ (C#和.NET 3.5的一个特性)。你查过了吗?

        4
  •  3
  •   Greg Hewgill    17 年前

    使用Boost。迭代器库,用于编写一个“选择”迭代器,例如,一个跳过所有不满足给定谓词的元素的迭代器。

    http://www.boost.org/doc/libs/1_39_0/libs/iterator/doc/filter_iterator.html

    无论如何,在C++中,基本上可以通过分层迭代器来实现相同的效果。

    如果你有一个常规迭代器,它访问序列中的每个元素,你可以把它包装在一个过滤迭代器中,过滤迭代器会递增底层迭代器,直到它找到一个满足条件的值。然后,您甚至可以将其包装在一个“选择”迭代器中,将值转换为所需的格式。

    这似乎是一个相当明显的想法,但我不知道它的任何完整实现。

        5
  •  1
  •   Max Lybbert    17 年前

    STL algorithms std::find_if std::lower_bound std::upper_bound (在已分类的容器上)。性能将与循环大致相同,但语法更具声明性。

    IQueryable

    BerkelyDB NetCDF , HDF5 , STXXL 等等。文件访问速度很慢,但这样做可以处理超出内存容量的数据。

        6
  •  1
  •   Community Mohan Dere    9 年前

    std::set< int > numbers;
    for ( int i = -10; i <= 10; ++i ) {
        numbers.insert( i );
    }
    
    std::set::iterator first = numbers.find(1);
    std::set::iterator end = numbers.end();
    

    现在,您可以从以下内容进行迭代 first 直到 end 填充和 O(log(n)) 寻找。迭代是 std::set::iterator

    std::find_if Max Lybbert's

    bool isPositive(int n) { return n > 0; }
    
    std::vector< int > numbers;
    for ( int i = -10; i <= 10; ++i ) {
        numbers.push_back( i );
    }
    
    for ( std::vector< int >::const_iterator end = numbers.end(), 
            iter = std::find_if(numbers.begin(), end, isPositive); // <- first positive value
          iter != end; 
          iter = std::find_if(iter, end, isPositive) // <- advance iter to the next positive
    ) {
    
        // iter is guaranteed to be positive here, do something with it!
    }
    

    如果你想在不实际连接到数据库的情况下获得更能唤起SQL的东西,你应该看看 Boost 尤其是 boost::multi_index 容器和boost迭代器。

        7
  •  0
  •   Colin    17 年前

    结账 Mono 若你们想在Linux/OSX上尝试LINQ,它是的一个移植。我相信.NET Framework和LINQ现在都包含在内了。