我有以下用例, 整数数组
vector<int> containing elements 123 345 678 890 555 ...
pos 0 1 2 3 4
基于我收到的比特表示,例如
101 then return 123 678 (Elements of the array with its position bits set)
0011 then return 678 890
00001 then return 555
你能推荐一些我可以用来解决这个问题的库。
编辑:向量本身是动态的,位大小可以根据想要返回相应数组元素的1位而变化。
答案 0 :(得分:4)
您最终希望将设置的位映射到其位索引。使用众所周知的比特笨拙的黑客很容易:
bit_mask_iterator= bits;
while (bit_mask_iterator)
{
long single_bit_set= bit_mask_iterator & -bit_mask_iterator;
long bit_index= count_bits_set(single_bit_set - 1); // this is the index you want
bit_mask_iterator&= bit_mask_iterator - 1;
}
其中count_bits_set
可以使用编译器内在或手动实现(请参阅http://www-graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel)。如果您愿意,也可以使用single_bit_set
找到log2。
答案 1 :(得分:1)
int bitMask = 11; // 1011 (reverse the bitmask when it comes in)
int count = 0;
vector<int> myVector (4);
vector<int> returnVector;
myVector[0] = 123;
myVector[1] = 356;
myVector[2] = 678;
myVector[3] = 890;
while (bitMask)
{
if (bitMask & 0x01)
{
returnVector.push_back (myVector[count]);
}
count++;
bitMask >>= 1;
}
答案 2 :(得分:1)
我假设位掩码存储在容器中(以支持系统上位数超过sizeof(uintmax_t)
的位掩码)。在这种情况下,解决方案的本质是:
std::remove_copy_if(v.begin(), v.end(), std::back_inserter(out),
!*boost::lambda::var(pred)++);
v
- 输入向量; out
- 存储结果的向量; pred
- 一个位掩码的迭代器。
如果你想避免boost::lambda
,那么很容易模拟它:
template <class InputIterator, class OutputIterator, class PredicateIterator>
void copy_if(InputIterator first, InputIterator last, OutputIterator result,
PredicateIterator pred) {
for ( ; first != last; ++first)
if (*pred++)
*result++ = *first;
}
可以如下使用(使用与上例中相同的表示法):
copy_if(v.begin(), v.end(), std::back_inserter(out), pred);
或使用谓词相同:
template <class Iterator>
class Pred {
Iterator it;
public:
Pred(Iterator it_) : it(it_) {}
template <class T>
bool operator ()(T /* ignore argument */) { return !*it++; }
};
template <class Iterator>
Pred<Iterator> iterator2predicate(Iterator it) {
return Pred<Iterator>(it);
}
可以使用如下:
std::remove_copy_if(v.begin(), v.end(), std::back_inserter(out),
iterator2predicate(pred));
示例(使用boost::lambda
,但很容易通过上述其他两个选项替换它):
/** g++ -Wall -Ipath/to/boost -o filter_array filter_array.cpp */
#include <algorithm>
#include <iostream>
#include <iterator> // back_inserter()
#include <vector>
#include <boost/lambda/lambda.hpp>
#define LEN(array) (sizeof(array) / sizeof(*(array)))
#define P(v) { std::for_each(v.begin(), v.end(), \
std::cout << boost::lambda::_1 << " "); \
std::cout << std::endl; }
int main() {
int a[] = {123, 345, 678, 890, 555,};
const size_t n = LEN(a);
bool bits[][n] = {
1, 0, 1, 0, 0,
0, 0, 1, 1, 0,
0, 0, 0, 0, 1,
};
typedef std::vector<int> Array;
Array v(a, a + n);
P(v);
for (size_t i = 0; i < LEN(bits); ++i) {
Array out;
std::vector<bool> b(bits[i], bits[i] + LEN(bits[i]));
std::vector<bool>::const_iterator pred = b.begin();
P(b);
std::remove_copy_if(v.begin(), v.end(), std::back_inserter(out),
!*boost::lambda::var(pred)++);
P(out);
}
}
输出:
123 345 678 890 555
1 0 1 0 0
123 678
0 0 1 1 0
678 890
0 0 0 0 1
555
答案 3 :(得分:0)
这是一个快速而肮脏的解决方案
vector<int> filtered;
char *bits = "0011";
for(int i = 0;i < sizeof(bits) ; i++)
if(bit[i] == '1')
filtered.push_back(myvector[i]);
return filtered
答案 4 :(得分:0)
好的,你可以使用过滤迭代器来做到这一点。正如我在你的问题上看到的那样,数组上的索引以与数字相反的顺序开始(数字的位置索引“0”对应于数组中的位置“3”)。因此,您必须反过来查看数组以选择正确的元素。此外,由于返回值可能包含0,1,2,3或4个元素,我建议您返回一个列表。这是一个提示:
struct filter
{
filter (int n) :number (n)
{
}
bool operator()(int other_number)
{
bool result = number & 1;
number>>=1;
return result;
}
int number;
};
int main(void)
{
using namespace std;
vector<int> my_v (4);
my_v[0] = 123;
my_v[1] = 356;
my_v[2] = 678;
my_v[3] = 890;
int bin_num = 10; // 1010
list<int> out_list;
std::copy(boost::make_filter_iterator (filter (bin_num),
my_v.rbegin(),
my_v.rend()),
boost::make_filter_iterator(filter (bin_num),
my_v.rend(), my_v.rend()),
std::front_inserter (out_list));
// out_list will have 123 678
}
希望这有帮助,