MW211 EXIT

devlog
PostgreSQL/配列を集約してさらに配列化
2013年01月30日
「ARRAY_AGG()」では配列をさらに配列として集約するのはできないのだろうか。
┌──────────────────────────────────────┐
│SELECT ARRAY_AGG(c) FROM (VALUES (ARRAY[1,2]),(ARRAY[3,4])) AS t(c);        │
└──────────────────────────────────────┘
ってやると以下のエラーがでる。(integer型に限った話ではなくtext型も)
「ERROR:  could not find array type for data type integer[]」

┌──────────────────────────────────────┐
│SELECT ARRAY_AGG(ROW(c)) FROM (VALUES (ARRAY[1,2]),(ARRAY[3,4])) AS t(c);   │
└──────────────────────────────────────┘
ROW式ってやつを使って見ると「{"(\"{1,2}\")","(\"{3,4}\")"}」という結果になる。

┌──────────────────────────────────────┐
│SELECT ARRAY_TO_STRING(ARRAY_AGG(ROW(c)),',')                               │
│    FROM (VALUES (ARRAY[1,2]),(ARRAY[3,4])) AS t(c);                        │
└──────────────────────────────────────┘
で、文字列に変換するとこうなる。「("{1,2}"),("{3,4}")」

配列を配列として集約、多次元配列的になるようだ。

ただし、求めたいのは「{1,2,3,4}」という結果。
一次元の配列にする方法はあるのだろうか?

ま、代案としては、CSV形式の文字列とかにして、最後に配列にするとかか。
分類:PostgreSQL、【未解決】
PostgreSQL/横のmin()とmax()
2013年01月27日
min()とmax()は行を跨いで、最小値および最大値を取得できるわけだが…。
┌──────────────────────────────────────┐
│SELECT min(列) FROM 表;                                                     │
│SELECT max(列) FROM 表;                                                     │
└──────────────────────────────────────┘

列を跨いで、最小値および最大値を取得する方法がある。これだ。
┌──────────────────────────────────────┐
│SELECT least(列,列…);                                                      │
│SELECT greatest(列,列…);                                                   │
└──────────────────────────────────────┘

こんな感じになる。
┌──────────────────────────────────────┐
│SELECT least(1,2,3);                                                     →1│
│SELECT greatest(1,2,3);                                                  →3│
└──────────────────────────────────────┘
分類:PostgreSQL
PostgreSQL/generate_series()の入れ子
2013年01月26日
AS演算子で別名にすりゃいい。
┌──────────────────────────────────────┐
│SELECT (SELECT array_agg(t1.c1 || '-' || t2.c1)                             │
│            FROM generate_series(1, 2, 1) AS t2(c1))                        │
│    FROM generate_series(1, 3, 1) AS t1(c1);                                │
└──────────────────────────────────────┘

但し、表名だけを別名にしてもダメ(列名も必要)だから注意。
┌──────────────────────────────────────┐
│SELECT (SELECT array_agg(t1.generate_series || '-' || t2.generate_series)   │
│            FROM generate_series(1, 2, 1) AS t2)                            │
│    FROM generate_series(1, 3, 1) AS t1;                                    │
└──────────────────────────────────────┘
分類:PostgreSQL
PostgreSQL/一時的な疑似テーブル
2013年01月18日
┌──────────────────────────────────────┐
│(VALUES(値,値),(値,値)) AS 表(列,列)                                        │
└──────────────────────────────────────┘
上記のような書式で一時的な疑似テーブルをつくることができる。

以下のような感じで使える。
┌──────────────────────────────────────┐
│SELECT * FROM (VALUES(1,'a'),(2,'b')) AS t(c1,c2);                          │
└──────────────────────────────────────┘
分類:PostgreSQL
JavaScript/残り文字数とアンドゥ
2013年01月17日
textareaタグの長文入力欄の文字数制限を実装する上で、
補助的に入力の度に残り文字数を更新するようにした。

ところが、この結果アンドゥ(ctrl+z)が効かなくなってしまった。

文字数を更新表示することにより、
入力した内容が確定してアンドゥが効かなくなるようだ。

長文入力する上で、アンドゥが効かないのは非常につらい。

ということで、残り文字数の表示は断念。

なんかいい代替案はないものか。
分類:JavaScript
設計/多階層のステータス管理
2013年01月15日
┌───┐
│○┬○│○…正常、×…異常、?…不明
│  └○│
└───┘
二階層以上でそれぞれステータスを持つ場合、上位ステータスが異常となった場合
下位ステータスにどのように反映させるか、以下の三つのパターンがある。
            ┌───┬───┬───┐
            │  A  │  B  │  C  │
┌───┐  ┌───┬───┬───┐  ┌───┐
│○┬○│  │×┬○│×┬×│×┬?│  │○┬○│
│  └○│  │  └○│  └×│  └?│  │  └○│
├───┤  ├───┼───┼───┤  ├───┤
│○┬×│  │×┬×│×┬×│×┬?│  │○┬×│
│  └○│  │  └○│  └×│  └?│  │  └○│
├───┤→├───┼───┼───┤→├───┤
│○┬○│  │×┬○│×┬×│×┬?│  │○┬○│
│  └×│  │  └×│  └×│  └?│  │  └×│
├───┤  ├───┼───┼───┤  ├───┤
│○┬×│  │×┬×│×┬×│×┬?│  │○┬×│
│  └×│  │  └×│  └×│  └?│  │  └×│
└───┘  └───┴───┴───┘  └───┘
  A:下位に反映させない      下位ステータス(正常)の遷移としては、○→○→○
  B:下位にすべて反映させる  下位ステータス(正常)の遷移としては、○→×→○
  C:下位をすべて不明とする  下位ステータス(正常)の遷移としては、○→?→○

外部向け(画面表示等)と内部管理で、分けるというのも一つの手だ。
たいてい、内部管理ではBを採用しづらい。
更新の量が莫大になり、差分による処理(履歴追加)なども莫大になりかねないからだ。
なので、内部的にはAで、外部向けとしてBもしくはCとするのが一般的か。
その間は、外部的には下位ステータスは×か?なのだから、
「○→×」的な遷移が発生しては辻褄が合わなくなることに注意だ。
分類:設計
C言語/可変引数関数
2013年01月14日
「f("%d", 1);」でも「f("%d-%d", 1, 2);」でも大丈夫な
可変引数をもつ関数の作り方。
┌──────────────────────────────────────┐
│#include <stdarg.h>                                                         │
│void f(const char *format, ...) {                                           │
│    va_list ap;                                                             │
│    char    buff[1024];                                                     │
│                                                                            │
│    va_start(ap, format);                                                   │
│    if (vsnprintf(buff, sizeof(buff), format, ap) < 0) {                    │
│        buff[0] = '\0';                                                     │
│    }                                                                       │
│    va_end(ap);                                                             │
│                                                                            │
│    printf("%s", buff);                                                     │
│}                                                                           │
└──────────────────────────────────────┘
「va_start()」から「va_end()」の区間において
「vsnprintf()」(他に「vsprintf()、vasprintf()」があるらしい)で、
文字列を統合して取得して、後はそれを使えばいいらしい。

詳しいことは追々。。。
分類:C/C++
C言語/文字列のコピー総集編
2013年01月13日
文字列の場合は、代入式は使えない。ということで以下はダメ。
┌──────────────────────────────────────┐
│出力先 = 入力元;                                                            │
└──────────────────────────────────────┘
「&出力先 = 入力元;」とか「&出力先 = &入力元;」とか足掻いてみてもダメ。
構造体の場合は代入式が使えるので、よく勘違いしがちだ。

では、どうするか?

まず、最凶なのは、「memcpy()」。これならなんでもできる。
┌──────────────────────────────────────┐
│memcpy(出力先, 入力元, sizeof(出力先));                                     │
└──────────────────────────────────────┘
ただし、末尾の「\0」を保証してくれないので、入力元の文字数が多いとアウト。
んな訳で、以下のような小細工を施したりする。
┌──────────────────────────────────────┐
│memset(出力先, 0 sizeof(出力先));                                           │
│memcpy(出力先, 入力元, sizeof(出力先) - 1);                                 │
└──────────────────────────────────────┘
まあ、なんつーか、文字をメモリとして機械的扱う感じだ。

じゃ次は、せっかくだから文字として扱ってやろうという話。
代表的なのはこれ、「strcpy()」。
┌──────────────────────────────────────┐
│strcpy(出力先, 入力元);                                                     │
└──────────────────────────────────────┘
こいつは、入力元の「\0」までを強制的にコピーしてしまうので、
扱いにはかなり慎重にならなければなるまい(メモリ侵犯しやすい)。
あらかじめ、出力先と入力元のサイズの関係が保証される時に使う感じか。
ま、予防策を講じるなら以下のような感じか。オールオアナッシングだけど。
┌──────────────────────────────────────┐
│if (strlen(入力元) < sizeof(出力先)) {                                      │
│    strcpy(出力先, 入力元);                                                 │
│}                                                                           │
└──────────────────────────────────────┘

続いて、進化形(?)の「strncpy()」。
┌──────────────────────────────────────┐
│strncpy(出力先, 入力元, sizeof(出力先));                                    │
└──────────────────────────────────────┘
サイズを指定できて、しかも入力元が短い場合、残りを「\0」で埋めてくれる。
ってことで、「strcpy()」よりも遅いらしい。
そしてなによりもこいつも末尾の「\0」を保証してくれない。
前出の「memcpy()」とほとんど同じやん。
やっぱり以下となってしまうのか?(これじゃあんまり使い道ないね)
┌──────────────────────────────────────┐
│memset(出力先, 0 sizeof(出力先));                                           │
│strncpy(出力先, 入力元, sizeof(出力先) - 1);                                │
└──────────────────────────────────────┘

そして、別分野から参入の「snprintf()」。これは使える。
┌──────────────────────────────────────┐
│snprintf(出力先, sizeof(出力先), "%s", 入力元);                             │
└──────────────────────────────────────┘
これだと「出力先≦入力元」でも、最後の末尾に「\0」を押し込めてくれる。
ま、その分最後の一文字は犠牲になるのだが、
「\0」がなくて例外になるよりはかなりまし。
多少速度が犠牲になるらしいが、「memset()」とか使って実装するなら、
一行で済むこいつにしてしまった方がいいのかも。

ま、これらをコングロマリット(?)してできた案が以下。
┌──────────────────────────────────────┐
│if (strlen(入力元) < sizeof(出力先)) {                                      │
│    strcpy(出力先, 入力元);                                                 │
│} else {                                                                    │
│    snprintf(出力先, sizeof(出力先), "%s", 入力元);                         │
│}                                                                           │
└──────────────────────────────────────┘
ま、速度が気になるなら一考かも。
分類:C/C++
設計/論理組合せ
2013年01月12日
真と偽を組み合わせて、16通りの結果を求める式は以下の通り。
─────────┬─────────┬─────────┬─────────
(×&&×)&&×  →×│(×≠×)&&!× →×│×&&×        →×│×||(×&&×)  →×
(×&&○)&&×  →×│(×≠○)&&!○ →×│×&&○        →×│×||(○&&×)  →×
(○&&×)&&×  →×│(○≠×)&&!× →○│○&&×        →×│○||(×&&×)  →○
(○&&○)&&×  →×│(○≠○)&&!○ →×│○&&○        →○│○||(○&&×)  →○
─────────┼─────────┼─────────┼─────────
!(×||×)     →○│(×&&×)||!× →○│×=×        →○│×||(×=×)  →○
!(×||○)     →×│(×&&×)||!○ →×│×=○        →×│×||(×=○)  →×
!(○||×)     →×│(○&&×)||!× →○│○=×        →×│○||(○=×)  →○
!(○||○)     →×│(○&&×)||!○ →×│○=○        →○│○||(○=○)  →○
─────────┼─────────┼─────────┼─────────
!×&&(×≠×) →×│×≠×        →×│(×&&×)||×  →×│×||×        →×
!×&&(×≠○) →○│×≠○        →○│(×&&×)||○  →○│×||○        →○
!○&&(○≠×) →×│○≠×        →○│(○&&×)||×  →×│○||×        →○
!○&&(○≠○) →×│○≠○        →×│(○&&×)||○  →○│○||○        →○
─────────┼─────────┼─────────┼─────────
!×||(×&&×) →○│!(×&&×)     →○│(×=×)||×  →○│(×&&×)||○  →○
!×||(○&&×) →○│!(×&&○)     →○│(×=○)||○  →○│(×&&○)||○  →○
!○||(×&&×) →×│!(○&&×)     →○│(○=×)||×  →×│(○&&×)||○  →○
!○||(○&&×) →×│!(○&&○)     →×│(○=○)||○  →○│(○&&○)||○  →○
─────────┴─────────┴─────────┴─────────
  ○:真、×:偽、=:等号、≠:不等号、&&:論理積、||:論理和、!:否定

他にも方法がありそうだけど。。。
分類:設計
C言語/ビット演算子と論理演算子
2013年01月11日
ビット演算子と論理演算子の組み合わせ対比表って以下みたいなのでいいのかな?
┌─────────┬─────────┬─────────┐
│                  │   ビット演算子   │    論理演算子    │
├─────────┼─────────┼─────────┤
│論理積            │  ○ & ○   → ○ │ (偽 && 偽) → 偽 │
│                  │  ○ & ●   → ○ │ (偽 && 真) → 偽 │
│                  │  ● & ○   → ○ │ (真 && 偽) → 偽 │
│                  │  ● & ●   → ● │ (真 && 真) → 真 │
├─────────┼─────────┼─────────┤
│論理和            │  ○ | ○   → ○ │ (偽 || 偽) → 偽 │
│                  │  ○ | ●   → ● │ (偽 || 真) → 真 │
│                  │  ● | ○   → ● │ (真 || 偽) → 真 │
│                  │  ● | ●   → ● │ (真 || 真) → 真 │
├─────────┼─────────┼─────────┤
│排他的論理和      │  ○ ^ ○   → ○ │ (偽 != 偽) → 偽 │
│                  │  ○ ^ ●   → ● │ (偽 != 真) → 真 │
│                  │  ● ^ ○   → ● │ (真 != 偽) → 真 │
│                  │  ● ^ ●   → ○ │ (真 != 真) → 偽 │
├─────────┼─────────┼─────────┤
│論理積の否定      │~(○ & ○)  → ● │!(偽 && 偽) → 真 │
│                  │~(○ & ●)  → ● │!(偽 && 真) → 真 │
│                  │~(● & ○)  → ● │!(真 && 偽) → 真 │
│                  │~(● & ●)  → ○ │!(真 && 真) → 偽 │
├─────────┼─────────┼─────────┤
│論理和の否定      │~(○ | ○)  → ● │!(偽 || 偽) → 真 │
│                  │~(○ | ●)  → ○ │!(偽 || 真) → 偽 │
│                  │~(● | ○)  → ○ │!(真 || 偽) → 偽 │
│                  │~(● | ●)  → ○ │!(真 || 真) → 偽 │
├─────────┼─────────┼─────────┤
│排他的論理和の否定│~(○ ^ ○)  → ● │ (偽 == 偽) → 真 │
│                  │~(○ ^ ●)  → ○ │ (偽 == 真) → 偽 │
│                  │~(● ^ ○)  → ○ │ (真 == 偽) → 偽 │
│                  │~(● ^ ●)  → ● │ (真 == 真) → 真 │
└─────────┴─────────┴─────────┘
分類:C/C++
前へ 1 2 次へ