- PR -

【C#】単一テキストファイルから重複行削除

投稿者投稿内容
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-06-13 11:06
入れ違いになってしまってますね^^;

引用:

ちづるさんの書き込み (2006-06-13 10:41) より:

if(text.ToString()= text2.ToString())ではそもそもの中身が違うので
=になるわけないですし、でも比較するにはうーん…と
悩んでます。


データの量が多いですし、削除するよりもコピーする方が効率は良いと思います。
つまり、重複していなければコピーする訳です。
そうすると削除処理自身が不用になります。

比較の方法ですが行単位になるので、レコードセパレーターに準じてSplit()で配列に格納してループを回します。
ループ無いでは、重複チェックして、重複していない行のみ、別の文字列なり配列に出力することを繰り返します。

最後に出力先の文字列なり配列をファイルに保存します。

コード:

for(int i = 0; i < SourceRecordArray.Length; i++) {
bool duplicateFlag = false;
for(int j = i + 1; j < SourceRecordArray.Length; j++) {
if (SourceRecordArray[i] == SourceRecordArray[j]) {
duplicateFlag = true;
break;
}
}
if (!duplicateFlag) {
出力する・・・
}
}
*書きなぐりなので動作保障はありませんw



[ メッセージ編集済み 編集者: R・田中一郎 編集日時 2006-06-13 11:13 ]
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-06-13 11:14
1行がどれくらいのボリュームかにもよりますが、10万行をメモリだけで処理するのはキツいかもですね。

とりあえず案を2つほど。

(1)Hashtableを使う方法
・ReadLineで1行ずつ読みながら、ループ
・読み込んだ1行のデータをキーにHashtableのItemを取得
 nullだったら初めて出てくるデータとして出力ファイルに書き込みつつ、
 HashtableのItemに読み込んだ行のデータをキーに適当な値(Trueとか1とかでおk)を登録

(2)データベースを使う方法
・空のワークテーブルを用意して、とりあえず全部Insert
・Select Distinctで取得してファイルに書き込み
・ワークテーブルからレコードを削除
ちづる
ベテラン
会議室デビュー日: 2004/07/27
投稿数: 72
投稿日時: 2006-06-13 11:53
>R・田中一郎様
削除ばかり目がいっていて、コピーは頭になかったです。
試してみます。


>ぼのぼの様
>1行がどれくらいのボリュームかにもよりますが、10万行をメモリだけで処理するのはキツいかもですね。
やはりそうですか・・・。
Hashtableと空のワークテーブルの方法、試してみます。


試してみた後、再度また書き込みさせていただきます。
R・田中一郎様、ぼのぼの様ありがとうございますm(_ _)m
ちづる
ベテラン
会議室デビュー日: 2004/07/27
投稿数: 72
投稿日時: 2006-06-13 13:46
>R・田中一郎様
Split()を使用してイメージどおりの処理を行う事ができました!
ありがとうございます!

>ぼのぼの様
Hashtableを使用してイメージどおりの処理ができました!
ありがとうございます!
(ワークテーブルはDBを実環境で使用できないので、試す事ができませんでした…)

まだサンプルデータで件数が少ない状態でしか試してないのですが、
実際問題、10万件レベルのデータだとレスポンス向上の為の
処理はこれ以外に存在したりするのでしょうか?
R・田中一郎
ぬし
会議室デビュー日: 2005/11/03
投稿数: 979
投稿日時: 2006-06-13 14:58
引用:

ちづるさんの書き込み (2006-06-13 13:46) より:

まだサンプルデータで件数が少ない状態でしか試してないのですが、
実際問題、10万件レベルのデータだとレスポンス向上の為の
処理はこれ以外に存在したりするのでしょうか?


件数も大事ですが、実際のファイルサイズはどのくらいあるんでしょう?
今川 美保(夏椰)
ぬし
会議室デビュー日: 2004/06/10
投稿数: 363
お住まい・勤務地: 神奈川県茅ヶ崎市
投稿日時: 2006-06-13 15:17
便乗質問というか・・・・
素朴な疑問ですが、

こんな感じでOLEDBとしてファイルを読み取り
SELECT DISTINCT で重複を省くってだめなんでしょうか?

一度もそういう手法が出てこないので、
推奨されない手法なの否かが気になったので。

コード:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.OleDb;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\;Extended Properties=\"text;HDR=NO;FMT=Delimited\"") ;
            OleDbCommand cmd = new OleDbCommand("select distinct *  from Test.txt", con);

            con.Open();
            OleDbDataReader dr = cmd.ExecuteReader();


            int rowcount = 0;
            while (dr.Read() == true)
            {
                rowcount++;
                Console.WriteLine(dr.GetValue(0));
            }

            Console.WriteLine(rowcount);
            con.Close();
    

        }
    }
}



_________________
夏椰 @ わんくま同盟
夏椰の庵
Microsoft MVP for Windows Server System - SQL Server ( Jul 2006 - Jun 2008 )
ちづる
ベテラン
会議室デビュー日: 2004/07/27
投稿数: 72
投稿日時: 2006-06-13 15:19
>件数も大事ですが、実際のファイルサイズはどのくらいあるんでしょう?
一行が60文字程度の行なので、
最大でも1MBくらいあると思います。

4万行(400KB)のデータを作成して実行してみたら、帰ってきませんでした…
というより、処理に時間がかかってるだけだと思いますが。

理想では10万行で5分〜6分くらいのレスポンスです。
(無理でしょうか?)
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-06-13 15:31
引用:

ちづるさんの書き込み (2006-06-13 15:19) より:
理想では10万行で5分〜6分くらいのレスポンスです。
(無理でしょうか?)


処理速度はマシンスペックに依存するので、時間だけを指標にされても
一概に可能不可能は決められません。

それはともかく、ReadToEnd+Splitで時間がかかってる気がします。
ReadLineでループさせたらどうなりますか?

引用:

夏椰さんの書き込み (2006-06-13 15:17) より:
こんな感じでOLEDBとしてファイルを読み取り
SELECT DISTINCT で重複を省くってだめなんでしょうか?

一度もそういう手法が出てこないので、
推奨されない手法なの否かが気になったので。


いや、単純に知らなかっただけですw
こんなやり方もあったんですね

スキルアップ/キャリアアップ(JOB@IT)