イテレータの走査範囲を上手くコントロールするには? – プログラミング – Home

イテレータの走査範囲を上手くコントロー...
 
通知
すべてクリア

[解決済] イテレータの走査範囲を上手くコントロールするには?


秋雨
 秋雨
(@秋雨)
ゲスト
結合: 15年前
投稿: 2
Topic starter  

よろしくお願いいたします。コンパイラはVS2008Expressです。
データの順位を求めるプログラムですが条件があります。
データは昇順に並んでおり、且つそのデータに同順位が含まれる場合の条件として
同順位がある場合は、順位間の平均を順位として用います。
(例)3位が3つあった場合は、(3位+4位+5位)÷3 = 4位 を順位
このような計算を行うプログラムを、このように実装しましたが、このプログラムは思い
通りの動作を行いません。
範囲を走査するイテレータの動作範囲が一定でなく不確定な範囲を走査してしまうかから
だと思われます。
double array[] = {1.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 7.0, 9.0, 10.0, 10.0, 10.0};
また。このように後半に同値のデータが連続する場合にも、範囲を逸脱してしまい、期待
通りの動作とはなりません。
このようなプログラムを実装するにはどのような、考えや設計を行えばよいのでしょうか。

#include <iostream> //cout
#include <vector>

// 範囲の平均値を取得
template <class T>
T Average(T t1, T t2)
{
T result = 0;
int limit;
limit = (int)t2;
for(int i = 0; i < limit; ++i) {
result += t1;
++t1;
}
return result/t2;
}

template <class Iterator, class OutputIterator>
void PartAverage(Iterator first, const Iterator last, OutputIterator out)
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
value_type tmp; // 反復値の総和
value_type ave; // 反復値の平均値
Iterator p, p2, p3; // 範囲を
bool IsNonLimit = true;
size_t Idx = 0; // 反復した回数
p = first;
Iterator const limit = last-1;
while(p != limit)
{
tmp = 0.0;
Idx = 0;
IsNonLimit = true;
for(p3 = p; p3 != limit; ++p3) {
p2 = p3;
++p2;
// 非連続データの出力
if( *p3 != *p2 && IsNonLimit == true )
{
*out = *p3;
++out;
++p;
break;
} else if(!IsNonLimit) {
// 連続データの出力
++Idx;
ave = Average<value_type>(*p3, Idx);
for(size_t i = 0; i < Idx; ++i) {
*out = ave;
++out;
}
++p;
break;
} else {
// 連続データのストック
tmp += *p3;
++Idx;
++p;
++p2;
if(*p!=*p2) {
IsNonLimit = false;
}
--p2;
}
}
}
}

using namespace std;
int main()
{
double array[] = {1.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 7.0, 9.0, 10.0};
vector<double>lhs(array, array+10);
vector<double>vec(10);
PartAverage<vector<double>::iterator , vector<double>::iterator>(lhs.begin(),
lhs.end(), vec.begin());
copy(vec.begin(), vec.end(), std::ostream_iterator<double>(cout, ));
return 0;
}


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

>(例)3位が3つあった場合は、(3位+4位+5位)÷3 = 4位 を順位

ちょっと質問。 三位がふたつあった場合は (3位+4位)÷2 = 3.5位 ?


返信引用
秋雨
 秋雨
(@秋雨)
ゲスト
結合: 15年前
投稿: 2
Topic starter  

επιστημη さんお世話になります。
>>三位がふたつあった場合は (3位+4位)÷2 = 3.5位 ?
はい、その通りです。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

↓こんなんでいいんかなー...(自信ナシ)

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <functional>

using namespace std;
int main()
{
double array[] = {1.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 7.0, 9.0, 10.0};

double* first = array;
double* last = array+10;

while ( first != last ) {
double* mid = adjacent_find(first, last, not_equal_to<double>());
if ( mid != last ) ++mid;
double rank = distance(array,first)+1 + (distance(first,mid)-1)/2.0;
while ( first != mid ) {
cout << rank << ' ';
++first;
}
}
return 0;
}


返信引用
季節はずれのゴムボート
 季節はずれのゴムボート
(@季節はずれのゴムボート)
ゲスト
結合: 15年前
投稿: 4
 

επιστημη さんお世話になります。
ありがとうございます。std::vector<T>の検証と
double array[] = {1.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 7.0, 9.0, 10.0, 10.0, 10.0};
最後の値が連続する場合も期待通りの結果が得られましたことを報告します。

#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <functional>

using namespace std;
int main()
{
//use T[]
double array[] = {1.0, 2.0, 2.0, 2.0, 5.0, 6.0, 7.0, 7.0, 9.0, 10.0};

double* first = array;
double* last = array+10;

while ( first != last ) {
double* mid = adjacent_find(first, last, not_equal_to<double>());
if ( mid != last ) ++mid;
double rank = distance(array,first)+1 + (distance(first,mid)-1)/2.0;
while ( first != mid ) {
cout << rank << ' ';
++first;
}
}
cout << \n;

//use std::vector<T>
vector<double>lhs(array, array+10);

vector<double>::iterator first_ = lhs.begin();
vector<double>::iterator last_ = lhs.end();

typedef vector<double>::iterator ITERATOR;

while ( first_ != last_ ) {
ITERATOR mid_ = adjacent_find(first_, last_, not_equal_to<double>());
if ( mid_ != last_ ) ++mid_;
double rank_ = distance(lhs.begin(),first_)+1 + (distance(first_,mid_)-1)/2.0;
while ( first_ != mid_ ) {
cout << rank_ << ' ';
++first_;
}
}
return 0;
}


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

アナタ誰?


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2659
 

ハンドルネームは、なるべく統一してほしいですね。
一々本人なのか確認するのは手間ですし。

故意ではないかもしれませんけれど、
なるべく統一する方向でお願いします。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

「複数ハンドルは別に構わんが辻褄は合わせておくれ」が僕の意見。
つか、「ちゃんと使えんものを使うな」かな。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました