矢量矢量。根据内部向量的特定索引删除重复项

时间:2014-08-09 15:43:13

标签: c++ vector unique combinations permutation

我一直在使用不同的变量和数据结构的组合,我不确定哪个是最好的实践。我不关心运行这些计算需要多长时间,我只关心最终结果。

我有一组价值观。 V - W - X - Y:Z.V,W,X和Y用于计算Z.V,W,X和Y各自具有256种不同的可能性。所以我相信我正在合作。

V - W - X - Y:Z

只要我的所有值都相同,顺序无关紧要,我仍会得到相同的结果。


0 - 52 - 115 - 249:0.059784

52 - 249 - 0 - 114:0.059784

249 - 52 - 114 - 0:0.059784


0 - 52 - 115 - 250:0.057423

0 - 250 - 115 - 52:0.057423

250 - 0 - 52 - 115:0.057423


0 - 52 - 115 - 251:0.055006

115 - 251 - 52 - 0:0.055006

251 - 0 - 52 - 115:0.055006


我需要我的最终结果是Z的这些值的列表。我真的不关心保存哪个组合来实现Z的唯一值。我只需要保留Z的值,这是一个浮点数(虽然最终结果我可以将它存储为我想的字符串),以及V,W,X,Y的值。

所以,如果我从这开始:

250 - 0 - 52 - 115:0.057423

0 - 52 - 115 - 249:0.059784

0 - 52 - 115 - 250:0.057423

52 - 249 - 0 - 114:0.059784

0 - 52 - 115 - 251:0.055006

0 - 250 - 115 - 52:0.057423

251 - 0 - 52 - 115:0.055006

249 - 52 - 114 - 0:0.059784

115 - 251 - 52 - 0:0.055006


我会以类似的方式结束:

250 - 0 - 52 - 115:0.057423

0 - 52 - 115 - 249:0.059784

115 - 251 - 52 - 0:0.055006


任何帮助/建议将不胜感激。非常感谢!


编辑:添加更多内容以帮助解读一些问题。

因此,我正在研究的整个项目的想法是计算四个数字电位器的每个可能的电阻,当你并行连接四个电位器时。我可以稍后计算一系列,但是现在平行是我所追求的。

电位器本身有一个A端子,B端子和抽头端子。我们正在寻找A端子和雨刮器端子之间的电阻。

这是一个1k欧姆的8位电位器。这意味着我们有256步的分辨率可以使用。为计算某一步的阻力,我们弄清楚:

trim = (((( (ohmRatingOfDigiPot)*(numberofPossibleSteps - stepToCalculate) )/numberofPOssileSteps)+wiperResistance)/1000);

所以,我们的等式结果是

trim  = (((( (1000)*(256-index) )/256)+50)/1000)

index是我们所在的步骤(总共256个步骤中)。

所以我找出了每个步骤的可能值,并将它们传递给一个数组。四电位器中四个电位器各一个。

for(int i = 0; i < 256; i++)
{
    trim  = (((( (1000)*(256-index) )/256)+50)/1000);
    index++;
    potOneSteps[i] = trim;
    potTwoSteps[i] = trim;
    potThreeSteps[i] = trim;
    potFourSteps[i] = trim;
}

是的,我知道可能有更好的方法。就像我说的那样,自从我使用C ++以来已经很久了。这很有效,我知道我还有其他需要担心的事情,所以它最终会留下来。哈

所以现在我需要在每种不同的组合中找出这四种电位器的每个可能值。 4个电位计,每个可能有256个值?带上for循环!

为了并行计算电阻的电阻,我们使用:

Total Resistance = ( 1 / ( (1/R1) + (1/R2) + (1/R3) + ... + (1/Rn))

对于我们的四个阵列,我想到了这个:

for (int A1W1 = 0; A1W1 < 256; A1W1++)
{
    for (int A2W2 = 0; A2W2 < 256; A2W2++)
    {
        for (int A3W3 = 0; A3W3 < 256; A3W3++)
        {
            for (int A4W4 = 0; A4W4 < 256; A4W4++)
            {
                rTrim = (1/((1/potOneSteps[A1W1]) + (1/potTwoSteps[A2W2]) + (1/potThreeSteps[A3W3]) + (1/potFourSteps[A4W4])));
            }
        }
    }
}

很长。处理器和内存非常密集。很差。我知道。我知道。

这是我能够考虑通过所有值来进行计算的唯一方法。不确定是否有更好的方法,对所有建议都持开放态度。

所以在我的原始帖子中,V - W - Y - X对应于计算Z的索引。 Z是我们使用所述指数的值计算的实际阻力。由于所有数组都是相同的,我们得到的重复值就像我在原帖中所说的那样。因此,我只需要知道Z / rTrim的唯一值以及找到它的步骤,以便获得所有可能的值,并能够将数字电位器设置为所述值。

我对所有变量/数据结构/等开放。没有什么必须设置为某种类型,所以我可以处理双打,浮点数,整数,数组,向量,集合,链表(哦,请不要!)等。

我希望这是有道理的。有点啰嗦,但我认为将所有信息都提供给我想要的东西是有益的。非常感谢!!


EDIT2:

我可能用PHP和mySQL(我的“原生”语言)解决了这个问题。如果你们还想伸出援助之手,我会全力以赴并愿意学习最佳实践,但不要觉得有义务。非常感谢您提供的帮助!

3 个答案:

答案 0 :(得分:2)

编辑:

我怀疑,你的问题不是从已计算的值数组中删除重复项。根据我对您的编辑的理解,您可以首先简单地计算必要的值而无需重复。

例如,想象一下0到3范围内的两个循环,如下所示:

for (int i = 0; i < 4; ++i) {
    for (int j = 0; j < 4; ++j) {
        someVectorOfPair.push_back(std::make_pair(i, j));
    }
}

在这里,您将获得从0到3的所有可能的有序值对。现在,您正在寻找所有可能的无序对,因此您考虑(0,1)和(1) ,0)重复。这是最简单的方法:

for (int i = 0; i < 4; ++i) {
    for (int j = i; j < 4; ++j) { // Only one character changed
        someVectorOfPair.push_back(std::make_pair(i, j));
    }
}

如果以i的当前值开始j,则不会计算对(x,y),其中y&lt; X。但是,你将得到所有其他组合,它似乎解决了你的问题。

哦,顺便说一句,(((( (1000)*(256-index) )/256)+50)/1000)可以这样写:(256.-i)/256. + 0.05。我不理解你的计算中的所有内容,但如果我可以后退,你可以进一步简化:i/256. + 0.05。如果iint,那么这里就是进行浮点计算。您也可以使用static_cast<double>(或float)进行投射。

原文:

您如何存储数据?你有多少数据?你怎么算Z?

如果没有这些问题的答案,我只能提出一种非常简单(但效率不高)的方法来实现目标:将数据复制到另一个矢量&#34;矢量&#34;重复检查。这大致是如何完成的(未经测试):

for (itD : data) {
    itR = std::find_if(result.begin(), result.end(), [&itD](result::iterator it) { it.Z == itD.Z });

    if (itR == result.end()) {
        result.push_back(*itD);
    }
}

然后,这并不是真正有效的。您还可以使用一组(有序或无)来存储结果:这样,插入会自动检查重复项(因为一组具有唯一键)。

答案 1 :(得分:2)

首先,让组合词正确:

给出每个项目的n个项目和d个可能性,n=4d=256在这里,我们有:

  • 如果顺序很重要的组合数量:d ^ n和256 ^ 4只是2 ^ 32 4 x 8 = 32位
  • 如果订单重要,formula在这种情况下(n+d-1)! / (d! * (n-1!)) ... 2.862.209 ~3M不同组合(比4G好很多)有序组合)

然而,考虑到n电阻器(并联或串联)的问题,不仅顺序不重要,而且即使组合本身只有在它们产生不同的总和时才是重要的/ EM>

  • 不同总和的数量(与probabilities相对)非常简单(n * d) - (n - 1)0 := 0 + 0 + 0 + 0的最低总和1020 := 255 + ... + 255和最高1021在这种情况下不同的金额。

那么,你应该做什么,扩展the answer of @PaulMc,就是根据4个值的总和来定义operator<,而不是它们可能不稳定的浮动结果。

但是,考虑到问题中的for循环,您仍然会插入设置4G(!)(256 ^ 4)次以填充1021个插槽。

所以,如果您已经知道订单并不重要,请以有效的方式填写订单,如果您获得所有组合并不重要,您只需要捕获所有不同的总和:

完整示例here /循环:

using Combination = std::array<int, n>;

...

std::set<Combination> all;
Combination c{}; // must value initialize a std::array to zero-init its int values
for (int pos = 0; pos != n; ++pos) {
    for (int i = 0; i != d; ++i) {
        c[pos] = i; // c[0] from 0..d (remains at d), then c[1] from 0..d, etc.
        all.insert(c);
    }
}

答案 2 :(得分:0)

您可以执行以下操作:

1)定义一个包含4个值和浮点值的类。

2)为此类定义operator <,用于比较浮点值。

3)定义此类的std::set并填充它。

以下是一个例子:

#include <set>
#include <vector>
#include <array>
#include <algorithm>
#include <iterator>
#include <ostream>
#include <iostream>

typedef std::vector<int> IntVector;

struct MyValueClass
{
    IntVector m_vals;
    double m_finalVal;
    bool operator < (const MyValueClass& c2) const 
    { return (m_finalVal < c2.m_finalVal);  }
    MyValueClass(const IntVector& v, double val) : m_vals(v), m_finalVal(val) {}
};

typedef std::set<MyValueClass> ValueClassSet;

using namespace std;
int main()
{
    vector<MyValueClass> mc;
    // Sample data
    mc.push_back(MyValueClass(IntVector{ 250, 0, 52, 115 }, 0.057423));
    mc.push_back(MyValueClass(IntVector{ 0, 52, 115, 249 }, 0.059784));
    mc.push_back(MyValueClass(IntVector{ 0, 52, 115, 250 }, 0.057423));
    mc.push_back(MyValueClass(IntVector{ 52, 249, 0, 114 }, 0.059784));
    mc.push_back(MyValueClass(IntVector{ 0, 52, 115, 251 }, 0.055006));
    mc.push_back(MyValueClass(IntVector{ 0, 250, 115, 52 }, 0.057423));
    mc.push_back(MyValueClass(IntVector{ 251, 0, 52, 115 }, 0.055006));
    mc.push_back(MyValueClass(IntVector{ 249, 52, 114, 0 }, 0.059784));
    mc.push_back(MyValueClass(IntVector{ 115, 251, 52, 0 }, 0.055006));

    // populate set with sample data from vector
    ValueClassSet ms;
    ValueClassSet::iterator it = ms.begin();
    copy(mc.begin(), mc.end(), inserter(ms, it));

    // output results
    ValueClassSet::iterator it2 = ms.begin();
    while (it2 != ms.end())
    {
        copy(it2->m_vals.begin(), it2->m_vals.end(), ostream_iterator<int>(cout, " "));
        cout << " : " << it2->m_finalVal << "\n";
        ++it2;
    }
}

Output:
0 52 115 251  : 0.055006
250 0 52 115  : 0.057423
0 52 115 249  : 0.059784

基本上,我们填充了您的信息向量,然后我们用向量填充set。由于std::set仅存储唯一值,因此仅存储唯一的Z项。我们为operator <类型设置的MyValueClassstd::set将用于确定某个项目是否已在该集合中的内容。

注意:我使用C++11初始化语法来填充向量。如果您正在使用C ++ 11之前的编译器,请使用旧式方式填充向量&#34;。