vector同士を併合し、ソートして重複をさせない様にするには? – プログラミング – Home

vector同士を併合し、ソートして重...
 
通知
すべてクリア

[解決済] vector同士を併合し、ソートして重複をさせない様にするには?


悠
 悠
(@悠)
ゲスト
結合: 17年前
投稿: 40
Topic starter  

お世話になっております。
タイトルにある様にSTLについてお知恵を拝借させて頂きたく思います。

typedef struct {
 std::string DisplayName;
 std::string TypeName;
   :
   :
   :
}FileInfo;

std::vector<FileInfo> ALLFiles;
std::vector<FileInfo> TmpFiles;

それぞれのVectorのFileInfo.DisplayNameで重複の判断を行い、ALLFilesを更新したく思
います。
昇順に並び替えて、重複を許さない様に併合するにはどの様にすれば宜しいでしょうか?

※現状のソースが以下の様になっていますが、実行時にFileInfo.DisplayNameの中身が
同名の場合に下記の様なエラーが出ます。
┌───────────────┐
|Debug Assertion Failed!    |
| …(中略)…          |
|Expression:invalid operation< |
|               |
|  [中止] [再試行] [無視]  |
└───────────────┘
operation<の箇所で不具合があるよと教えてくれているのでしょうが、
何処が間違っているのか判りません。

//-- ソース --
typedef struct {
 std::string DisplayName;
 std::string TypeName;
   :
  (中略)
   :
}FileInfo;

bool operator<(const FileInfo& FI1, const FileInfo& FI2)
{
 INT flg = FI1.FileName.compare(FI2.FileName);
 return((!flg) ? true : ((flg > 0) ? true : false));
}

void func(void)
{
 std::vector<FileInfo> ALLFiles;
 std::vector<FileInfo> TmpFiles;
   :
  (中略)
   :
 // 現在のファイル情報をsetに反映させ、ソートさせる
 std::set<FileInfo> setWork(TmpFiles.begin(), TmpFiles.end());

 // そこへ既にある情報をソート&併合する
 // (新旧に同名が存在する場合は新しい情報を残す)
 setWork.insert(ALLFiles.begin(), ALLFiles.end());

 // ALLFilesへ併合させた情報を反映させる
 ALLFiles.clear();
 ALLFiles.insert(ALLFiles.end(), setWork.begin(), setWork.end());
}


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

> std::vector<FileInfo> ALLFiles;
> std::vector<FileInfo> TmpFiles;
> 昇順に並び替えて、重複を許さない様に併合するにはどの様にすれば宜しいでしょう
か?

TmpFilesにある各要素に対し、
- それがALLFilesになければ追加
- それがALLFilesにあれば差し替え
でしょうか?

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

struct FileInfo {
int code;
int value;

FileInfo(int c, int v =0) : code(c), value(v) {}
};

inline bool operator<(const FileInfo& x, const FileInfo& y) {
return x.code < y.code;
}

std::ostream& operator<<(std::ostream& stream, const FileInfo& fi) {
return stream << '(' << fi.code << ',' << fi.value << ')';
}

int main() {
std::vector<FileInfo> ALLFiles;
std::vector<FileInfo> TmpFiles;
for ( int i = 19; i >= 0; --i ) {
if ( i % 2 == 0 ) {
ALLFiles.push_back(FileInfo(i,0));
}
if ( i % 3 == 0 ) {
TmpFiles.push_back(FileInfo(i,1));
}
}

std::ostream_iterator<FileInfo> out(std::cout, );
std::cout << --- ALL ---\n;
std::copy(ALLFiles.begin(), ALLFiles.end(), out); std::cout << std::endl;
std::cout << --- Tmp ---\n;
std::copy(TmpFiles.begin(), TmpFiles.end(), out); std::cout << std::endl;
std::cout << --- sort ALL ---\n;
std::sort(ALLFiles.begin(), ALLFiles.end());
std::copy(ALLFiles.begin(), ALLFiles.end(), out); std::cout << std::endl;
std::cout << --- merge ---\n;
int limit = ALLFiles.size();
for ( int i = 0; i < TmpFiles.size(); ++i ) {
std::vector<FileInfo>::iterator iter = std::lower_bound(ALLFiles.begin(),
ALLFiles.begin()+limit, TmpFiles[i]);
if ( TmpFiles[i] < *iter ) {
ALLFiles.push_back(TmpFiles[i]);
} else {
*iter = TmpFiles[i];
}
}
std::sort(ALLFiles.begin(), ALLFiles.end());
std::copy(ALLFiles.begin(), ALLFiles.end(), out); std::cout << std::endl;
}


返信引用
iijima
 iijima
(@iijima)
ゲスト
結合: 21年前
投稿: 44
 

bool operator < ( const FileInfo& FI1, const FileInfo& FI2 ) {
return FI1.DisplayName < FI2.DisplayName;
}

でもうまくいきませんか?

# 質問中のoperator < の定義でFileInfoクラスにないメンバ名FileNameが使われて
# いるので、アサートの原因については何とも。。。


返信引用
悠
 悠
(@悠)
ゲスト
結合: 17年前
投稿: 40
Topic starter  

こんにちは。

>επιστημηさん
提示して頂いたコードの動作を確認しました。
この動きが意図している動作です。
int code; を std::string に変更して動作を確認した所、
(当たり前ですが)同じ挙動を行った事を確認しました。
ただ今回はoperator<にてDebug Assertion Failed!が出ていたので、
そちら対処で何とかなるのかなと思います。
ありがとうございます。

>iijimaさん
>bool operator < ( const FileInfo& FI1, const FileInfo& FI2 ) {
> return FI1.DisplayName < FI2.DisplayName;
>}
此処の条件は、オペレータと同じく「<」で良いのですか。。
てっきり、ソートする対象に合わせてcompare()で文字列との比較を行うのかと
思っていました。

># 質問中のoperator < の定義でFileInfoクラスにないメンバ名FileNameが使われて
># いるので、アサートの原因については何とも。。。
済みません、こちらの転記ミスです。正しくはDisplayNameになります。

iijimaさんの提示して頂いた内容に修正したところ、同名がいくつあっても意図した動作
になっている事を確認致しました。
ありがとうございました。


返信引用
iijima
 iijima
(@iijima)
ゲスト
結合: 21年前
投稿: 44
 

> 此処の条件は、オペレータと同じく「<」で良いのですか。。

std::string型ですから。。

> てっきり、ソートする対象に合わせてcompare()で文字列との比較を行うのかと
> 思っていました。

もちろんcompareも使えるけど、↓で良いんでないかなぁ。

bool operator < ( const FileInfo& FI1, const FileInfo& FI2 ) {
return FI1.DisplayName.compare( FI2.DisplayName ) < 0;
}


返信引用
悠
 悠
(@悠)
ゲスト
結合: 17年前
投稿: 40
Topic starter  

>std::string型ですから。。
了解です。

>return FI1.DisplayName.compare( FI2.DisplayName ) < 0;
0との比較結果を返すのですか。
ニアピンだったみたいですね。

ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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