|
海外の重複を削除して数字の25と10を合計した結果を出力して ソートで並び替える方法ないでしょうか? 自分が考えたのがtokenとifと配列を使えばいけそうな気がするのですが、コードが思いつきません。お力を貸して頂けないでしょうか?
[元] 関東:322 関西:99 東海:30 海外:25 海外:10 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1
[希望処理] 関東:322 関西:99 海外:35 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1
|
No.4770 2017/12/04(Mon) 12:52:26
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
元が下記の場合でできました。 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10
---------------------
call C:\Users\aruke\Desktop\ショットカット構文一覧\00_共通化.uws
file="C:\Users\aruke\Desktop\1.txt" search="イギリス,欧州,北米,南米,インド:" search1="シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:" file1="C:\Users\Desktop\a.txt"
fid=fopen(file, F_read or F_WRITE) gyou=fget(fid,-1) for i = 1 to gyou naiyou=fget(fid,i) if pos(search,naiyou) then a=pos(":",naiyou) b=copy(naiyou,a+1) elseif pos(search1,naiyou) then a1=pos(":",naiyou) b1=copy(naiyou,a1+1) endif next goukei=val(b)+val(b1)
for i = 1 to gyou naiyou=fget(fid,i) if pos(search,naiyou) then FDELLINE(fid,i) elseif pos(search1,naiyou) then endif next
for i = 1 to gyou naiyou=fget(fid,i) if pos(search1,naiyou) then FDELLINE(fid,i) endif next fput(fid,"海外:"+goukei)
zen=fget(fid,-2) zen=COMMON.sort1(zen) COMMON.Write_ALLText(file1,zen)
|
No.4775 2017/12/05(Tue) 11:23:35
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / Liners |
|
No.4776 2017/12/05(Tue) 13:45:40
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / しゅん |
|
|
// 解決済みっぽいですけど、私ならという例を。
OPTION EXPLICIT
TEXTBLOCK data 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10 ENDTEXTBLOCK
// 文字列からデータ取り出しと重複を考慮した加算処理 // データの保持形式がこんなでなければ、もうちょっと簡単にかけるかも // 別ファイルの場合、FGETのF_ALLTEXTあたりで全体読み込めばOKかな DIM oc[] = "関東;関西;東海;中国;北海道;四国;九州,沖縄;東北", "海外" DIM reg = CREATEOLEOBJ("VBScript.RegExp") reg.Pattern = "(([^:]*):(\d*)(?:\r\n|$))" reg.Global = TRUE HASHTBL dup DIM m, key FOR m IN reg.Execute(data) key = m.SubMatches(1) IF !POS(key, oc[0]) THEN key = oc[1] dup[key] = dup[key] + VAL(m.SubMatches(2)) NEXT
// ソート準備 DIM i, n = LENGTH(dup) - 1, keys[n], vals[n] FOR i = 0 TO n keys[i] = dup[i, HASH_KEY] vals[i] = dup[i, HASH_VAL] NEXT
// ソート // 安定ソートじゃないけどね // 安定ソートにしたかったら、http://d.hatena.ne.jp/junjun777/20150611/uwsc_stable_sort QSORT(vals, QSRT_D, keys)
// 結果出力 FOR i = 0 TO LENGTH(keys) - 1 MSGBOX(keys[i] + ":" + vals[i]) NEXT
|
No.4778 2017/12/05(Tue) 20:53:16
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
Liners様、解決はできましたが今後の為にもっと簡潔なコードで書けるようなら教えて頂きたいです。
|
No.4779 2017/12/06(Wed) 10:47:17
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
しゅん様、返信ありがとうございます。希望通りの処理ができました。
今の私の実力では下記の処理がどういう意味合いかが理解できません。 自分なりの解釈してみたのですが分からない所があります。
oc[]の配列[0]が"関東;関西;東海;中国;北海道;四国;九州,沖縄;東北"、配列[1]が"海外"になっている。 forinと正規表現でm.SubMatches(1)で関東:322からシンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10までを変数keyにいれて、!POS(key, oc[0])のコードの意味は各行のデータが"関東;関西;東海;中国;北海道;四国;九州,沖縄;東北"になければ"海外"を変数keyにいれる
下記のコードの意味が分かりません。 dup[key] = dup[key] + VAL(m.SubMatches(2))
|
No.4780 2017/12/06(Wed) 11:24:37
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / Liners |
|
|
私的「簡素感」で書きます。基本、代入のみです♪ しゅんさんと同じですが、解説用に標準機能のみで変数に漢字を使います。
TEXTBLOCK 元データ 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10 ENDTEXTBLOCK
海外置換後 = replace(元データ, "イギリス,欧州,北米,南米,インド", "海外") 海外置換後 = replace(海外置換後, "シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア", "海外") hashtbl 連想配列
For 行内容 in Split(海外置換後, "<#cr>", TRUE) 地域 = token(":", 行内容) //残りは数値になる 連想配列[地域] = 連想配列[地域] + val(行内容) //各地域ごとの数量が加算される Next dim 配列上限 = length(連想配列) -1, 希望データ[配列上限], 数値[配列上限]
For i = 0 to 配列上限 数値[i] = 連想配列[i, HASH_VAL] 希望データ[i] = 連想配列[i, HASH_KEY] + ":" + 数値[i] Next qsort(数値, QSRT_D, 希望データ) SLCTBOX(SLCT_LST, 0,"配列内容", 希望データ)
|
No.4781 2017/12/06(Wed) 15:48:03
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / しゅん |
|
|
Linersさんの回答の方が、標準機能ですし、シンプルなので良いと思いますが、一応回答しておきます。
> oc[]の配列[0]が"関東;関西;東海;中国;北海道;四国;九州,沖縄;東北"、配列[1]が"海外"になっている。
海外変換用の配列です。 配列を使うのが適切かと言われると、不適切かもしれませんが、まとめたかったのでこうしました。 サンプルデータでは「海外」が固定のようですが、国内以外を海外にした方がよかろう、という考えから、国内をセミコロン区切りで確保し、その中に一致しないものは「海外」に置き換えるため、用意した次第です。
> forinと正規表現でm.SubMatches(1)で(以下略)
for-in構文で、mは「関東:322」〜「シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10」にマッチします。 m.SubMatches(0)は正規表現の一番左の括弧に対応、すなわち最初は「関東:322」に一致。 m.SubMatches(1)は正規表現の二番目の括弧に対応、すなわち最初は「関東」に一致。 m.SubMatches(2)は正規表現の二番目の括弧に対応、すなわち最初は「322」に一致。 一旦、keyに「関東」を入れて、oc[0]を探すと「関東」はあるので、keyはそのまま。 で、続いて、、、
> 下記のコードの意味が分かりません。 > dup[key] = dup[key] + VAL(m.SubMatches(2))
に入り、連想配列dupの「関東」のキーに「322]を数値かして加算する、ということです。 連想配列がどういうものか、というのを調べられることをオススメします。
|
No.4785 2017/12/06(Wed) 18:44:32
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
Liners様、回答ありがとうございます。Liners様のコードを見て勉強させた頂いたのですが、連想配列難しいですね。
数値[i] = 連想配列[i, HASH_VAL]の連想配列[i, HASH_VAL]を 希望データ[i] = 連想配列[i, HASH_KEY] + ":" + 連想配列[i, HASH_VAL]にした場合、海外:35がソートされない。
TEXTBLOCK 元データ 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10 ENDTEXTBLOCK
海外置換後 = replace(元データ, "イギリス,欧州,北米,南米,インド", "海外") 海外置換後 = replace(海外置換後, "シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア", "海外") hashtbl 連想配列
For 行内容 in Split(海外置換後, "<#cr>", TRUE) 地域 = token(":", 行内容) //残りは数値になる // msgbox(行内容) // msgbox("地域"+地域) // msgbox(連想配列[地域]) // 連想配列[地域] = val(行内容) // 連想配列[地域] = 連想配列[地域] + val(行内容) //各地域ごとの数量が加算される Next dim 配列上限 = length(連想配列) -1, 希望データ[配列上限], 数値[配列上限]
For i = 0 to 配列上限 希望データ[i] = 連想配列[i, HASH_KEY] + ":" + 連想配列[i, HASH_VAL] Next qsort(数値, QSRT_D, 希望データ) for i in 希望データ print i next pid = getid(GET_LOGPRINT_WIN)
text = getstr(pid, 1, STR_ACC_EDIT)
SENDSTR(0,text)
LOGPRINT(FALSE)
結果 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 海外:35 --------------------- Liners様の回答はうまくソートされている。
TEXTBLOCK 元データ 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10 ENDTEXTBLOCK
海外置換後 = replace(元データ, "イギリス,欧州,北米,南米,インド", "海外") 海外置換後 = replace(海外置換後, "シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア", "海外") hashtbl 連想配列
For 行内容 in Split(海外置換後, "<#cr>", TRUE) 地域 = token(":", 行内容) //残りは数値になる 連想配列[地域] = 連想配列[地域] + val(行内容) //各地域ごとの数量が加算される Next dim 配列上限 = length(連想配列) -1, 希望データ[配列上限], 数値[配列上限]
For i = 0 to 配列上限 数値[i] = 連想配列[i, HASH_VAL] 希望データ[i] = 連想配列[i, HASH_KEY] + ":" + 数値[i] Next qsort(数値, QSRT_D, 希望データ) for i in 希望データ print i next pid = getid(GET_LOGPRINT_WIN)
text = getstr(pid, 1, STR_ACC_EDIT)
SENDSTR(0,text)
LOGPRINT(FALSE)
結果 関東:322 関西:99 海外:35 東海:30 中国:4 九州,沖縄:2 四国:2 北海道:2 東北:1 --------------------- 連想配列[地域] = 連想配列[地域] + val(行内容)の連想配列[地域]には25が入っている。
TEXTBLOCK 元データ 関東:322 関西:99 東海:30 中国:4 北海道:2 四国:2 九州,沖縄:2 東北:1 イギリス,欧州,北米,南米,インド:25 シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア:10 ENDTEXTBLOCK
海外置換後 = replace(元データ, "イギリス,欧州,北米,南米,インド", "海外") 海外置換後 = replace(海外置換後, "シンガポール,マレーシア,インドネシア,中国,香港,韓国,アジア", "海外") hashtbl 連想配列
For 行内容 in Split(海外置換後, "<#cr>", TRUE) 地域 = token(":", 行内容) //残りは数値になる 連想配列[地域] =val(行内容) //各地域ごとの数量が加算される Next dim 配列上限 = length(連想配列) -1, 希望データ[配列上限], 数値[配列上限]
For i = 0 to 配列上限 数値[i] = 連想配列[i, HASH_VAL] 希望データ[i] = 連想配列[i, HASH_KEY] + ":" + 数値[i] Next qsort(数値, QSRT_D, 希望データ) for i in 希望データ print i next pid = getid(GET_LOGPRINT_WIN)
text = getstr(pid, 1, STR_ACC_EDIT)
SENDSTR(0,text)
LOGPRINT(FALSE)
連想配列[地域] =val(行内容)にすると、 結果、海外が10で25が入っていない。
関東:322 関西:99 東海:30 海外:10 中国:4 九州,沖縄:2 四国:2 北海道:2 東北:1 --------------------
連想配列の単純化した使用例参考
[連想配列の使用例] // パブリック、大・小文字区別しない、キーは書込み順 PUBLIC HASHTBL B // 大・小文字区別、キーはソート HASHTBL A = HASH_CASECARE or HASH_SORT A["あ"] = 1 A["う"] = 3 A["お"] = 5 A["え"] = 4 A["い"] = 2 A["お"] = 9 // "う"の値は何? print "'う' の値は " + A["う"] // "え"があれば削除 ifb A["え", HASH_EXISTS] // 必要無くとも変数で受ける flg = A["え", HASH_REMOVE] endif // ソート順で表示 (文字型での昇順ソート) for n = 0 to Length(A)-1 print A[n, HASH_KEY] + " = " + A[n, HASH_VAL] next
|
No.4793 2017/12/09(Sat) 12:29:12
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
しゅん様、返信ありがとうございます。正規表現の質問になってしまって恐縮ですが、ずっと考えていてなかなか解釈に難航しています。 ([^:]*):(\d*)(?:\r\n|$)部分をSubMatches(0)と考える。そしてSubMatches(1)は([^:]*)の部分、SubMatches(2)は(\d*)の部分という考え方も合っていますでしょうか?質問ばかりで申し訳ないですが、(?:\r\n|$)の意味は、?は直前の文字の0または1回にマッチ、\nは改行にマッチ、\r キャリッジリターン(行頭復帰)にマッチ、|は複数の文字列を1つの正規表現にまとめ、そのうちのいずれかにマッチ、$は行末にマッチという意味で合っていますでしょうか?
|
No.4794 2017/12/09(Sat) 13:33:03
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
まとめてみました。
共通 forinで連想配列にデータ挿入 fornextで連想配列からデータ読み出し // 順列読出し 変数[順列番号, HASH_KEY] // キーを返す 変数[順列番号, HASH_VAL] // 値を返す
しゅん様のソース 正規表現のサブマッチを使い:の左側、右側をそれぞれ抽出。
Liners様のソース tokenを使い:の左側取得、token後は 行内容は右側の取得可能になるのを利用。
|
No.4795 2017/12/09(Sat) 14:05:22
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / Liners |
|
|
>連想配列難しいですね。 多くの人が最初はそう思うものです。一次元だけだし、ソートはしにくいし、ループも回しにくい。こんなの意味あるの?
しかし、先人達は比較的初期の段階でこの機能を実装しました。今では、ほとんどの言語が実装している重要な機能です。 にもかかわらず、効果的な例はなかなか見ないですね。使える人には、当たり前すぎて初心者には、馴染みがないのです。
話を戻して、連想配列[地域] =val(行内容)にすると、結果、海外が10で25が入っていない。 連想配列は、引数が数字以外も使える配列なので、迷ったら普通の配列に置換えて考えると良いですよ。
A[0] = 25 A[0] = 10 // 結果:10
A[0] = A[0] + 25 // 最初は25 A[0] = A[0] + 10 // 結果: 35
今回の例は、連想配列が持つ「潜在能力」のほんの一例です。 参考URL: https://ja.wikipedia.org/wiki/%E9%80%A3%E6%83%B3%E9%85%8D%E5%88%97
考えてみると、私たちは、多くの物を番号ではなく名前で呼びます。そのくらい応用範囲は広がります。
|
No.4796 2017/12/09(Sat) 17:27:50
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / せきしんご |
|
|
Liners様、今回の連想配列のコードは連想配列の可能性を感じさせてくれるものでした、ありがとうございます。自分なりに提示頂いた回答を解釈しているのですが、以下の解釈であってますでしょうか?
Aの配列0に25を代入、Aの配列0に10を上書きしている A[0] = 25 A[0] = 10 // 結果:10
Aの配列0に25を代入、Aの配列0の25と10を足してA[0]は35になる A[0] = A[0] + 25 // 最初は25 A[0] = A[0] + 10 // 結果: 35
連想配列[地域] = 連想配列[地域] + val(行内容)の連想配列[地域] には25が入っている。この連想配列[地域]の意味はhashtbl 連想配列の連想配列と、地域 = token(":", 行内容)の地域を利用している。意味合いとしては、A["あ"] = 1みたいな使い方をしているという解釈であってますでしょうか?
// For 行内容 in Split(海外置換後, "<#cr>", TRUE) 地域 = token(":", 行内容) //残りは数値になる 連想配列[地域] = 連想配列[地域] + val(行内容) //各地域ごとの数量が加算される Next
--------------------- (連想配列例) HASHTBL A = HASH_CASECARE or HASH_SORT A["あ"] = 1 A["う"] = 3 A["お"] = 5 A["え"] = 4 A["い"] = 2 A["お"] = 9
|
No.4797 2017/12/09(Sat) 19:54:01
|
|
☆ Re: 海外の重複を削除して数字の25と10を合計した結果を出力してソート / しゅん |
|
|
> ([^:]*):(\d*)(?:\r\n|$)部分をSubMatches(0)と考える。そしてSubMatches(1)は([^:]*)の部分、SubMatches(2)は(\d*)の部分という考え方も合っていますでしょうか?
あっています。
> 質問ばかりで申し訳ないですが、(?:\r\n|$)の意味は、?は直前の文字の0または1回にマッチ、\nは改行にマッチ、\r キャリッジリターン(行頭復帰)にマッチ、|は複数の文字列を1つの正規表現にまとめ、そのうちのいずれかにマッチ、$は行末にマッチという意味で合っていますでしょうか?
だいたい良いです。 すみません、あんまり意味ないのに「(?:」を使ってしまいました。 「(」に続き「?:」と書いた場合、キャストしない、という特別な意味になります。 キャストしない、というのは、SubMatchesに加えない、とほぼ等価です。 今回の場合「(([^:]*):(\d*)(?:\r\n|$))」と括弧でくくられる部分は4つあります。 しかし、SubMatchesは0〜2の3つしかありません。 「?:」をとると、最後の改行をとってくるので、SubMatches(3)まで格納されます。 他はその通りです。 「(\r\n|$)」は、Windows標準の改行、または、文末に一致する正規表現です。
|
No.4805 2017/12/11(Mon) 09:09:14
|
|