早く流れる川で

雑に書き留めた何か

C#, LINQでGroupByしたコレクション内の数値の合計を得る

はじめに

C#LINQを用いて名前やID別で値を集計したい。

開発環境諸々

名前空間

using System;
using System.Linq;

集計対象

var hoges = new[]
{
    new {Name = "a", Score = 1},
    new {Name = "a", Score = 2},
    new {Name = "a", Score = 3},
    new {Name = "b", Score = 4},
    new {Name = "b", Score = 5},
};

GroupByでまとめたりSumったり

var query = hoges
    .GroupBy(item => item.Name)
    .Select(item => new
    {
        Name = item.Key,
        TotalScore = item.Sum(x => x.Score)
    });

結果確認

foreach(var item in query)
{
    Console.WriteLine(item);
}

実行結果

{ Name = a, TotalScore = 6 }
{ Name = b, TotalScore = 9 }

所感

LINQ便利!何かしら集計するときに使える!

Google Chrome Extensions, Hello Extensions!と表示する

はじめに

Google Chrome Extensionsのチュートリアルを試す。
Google Chrome Extensionsはmanifest.jsonと任意の名称のhtmlファイルを1つ、アイコン用のpngファイルを1つ用意する。

動作環境

開発環境

工程

  1. Google Chrome Extensionsの各ファイルを置くフォルダーを作成する
    • このフォルダーにjson, html, pngファイルを置く
  2. manifest.jsonを作成し、必要事項を記入する
  3. Hello Extensions!と表示するhtmlファイルを作成する
  4. アイコン用のpngファイルを用意する
  5. Google Chromechrome://extensions/にアクセス
  6. デベロッパー モードをONにする
  7. パッケージ化されていない拡張機能を読み込むボタンを押し、工程1で作成したプロジェクトフォルダーを指定する
  8. 追加したGoogle Chrome Extensionsを試す
  9. ※ところどころの工程は省略する

工程2 manifest.jsonを作成し、必要事項を記入する

{
    "manifest_version" : 2,
    "name" : "Hello Extension",
    "description" : "Base Level Extension",
    "version" : "0.1.0.0",
    "browser_action" : {
        "default_popup" : "hello.html",
        "default_icon" : "comment128.png"
    },
    "commands" : {
        "_execute_browser_action" : {
            "suggested_key" : {
                "default" : "Ctrl+Shift+F",
                "mac": "MacCtrl+Shift+F"
            },
            "description" : "Open hello.html"
        }
    }
}
  • browser_actiondefault_popupに後工程で作成するhtmlファイルの名称を記入
  • browser_actiondefault_iconに後工程で追加するpngファイルの名称を記入
  • commandsは省略しても良い
    • キー入力でGoogle Chrome Extensionsを起動させたいなら追加しておく

工程3 Hello Extensions!と表示するhtmlファイルを作成する

<html>
    <body>
        <h1>Hello Extensions!</h1>
    </body>
</html>
  • ほぼお手本のまま

工程4 アイコン用のpngファイルを用意する

工程6 デベロッパー モードをONにする

f:id:HayaUp:20200421233124p:plain

  • 画面右上にドグルスイッチがあるのでONにする

工程8 追加したGoogle Chrome Extensionsを試す

f:id:HayaUp:20200421233155p:plain

  • Google Chrome Extensionsは追加するとアドレスバーの右側に表示される
  • 設定したアイコン用のpngファイルがボタンに表示される

所感

意外と簡単に出来た。
業務でちょっとあったら便利だなーと思うものを作ってみたい。

Vue.js, computedは1または2回実行するのか?

はじめに

TLを眺めていたら次の書き込みがあった。
https://twitter.com/mpyw/status/1251517636984352768
ここのところVue.jsを触れていなかったので復習のつもりで確認した。

動作環境

開発環境

  • Editor
  • Vue.js
    • Version 2.6.11
      • console.log(Vue.version);で確認した

結論

結論から書くとcomputedは1回実行した。

ソースコード全文

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello, computed!</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <div>{{ foo }}</div>
        <div>{{ bar }}</div>
        <div>{{ fooAndBar }}</div>
        <div>
            <button v-on:click="Test">押してね!</button>
        </div>
    </div>

    <script>
        console.log(Vue.version);

        var app = new Vue({
            el: '#app',
            data: {
                foo : 1,
                bar : 1
            },
            computed : {
                fooAndBar : function() {
                    console.log("computed");
                    return this.foo + this.bar;
                }
            },
            methods : {
                Test : function() {
                    this.foo = 2;       // fooAndBarで利用しているプロパティを変更
                    this.bar = 3;       // 〃
                }
            },
            watch : {
                foo : function(newValue, oldValue) {
                    console.log(`new : ${newValue}, old : ${oldValue}`)
                },
                bar : function(newValue, oldValue) {
                    console.log(`new : ${newValue}, old : ${oldValue}`)
                }
            }
        });
    </script>
</body>
</html>

所感

v-on:clickmethodsの存在を忘れていた・・・。
編集していて思い出した。watchはおまけ。
触れていないと忘れてしまう。

JavaScript, Notification APIを使ってトースト通知をする、その2

はじめに

前回のNotificationのインスタンスを作成した後のオブジェクトはどうするんだ?と気になったので調べた。

動作環境

開発環境

イベントを設定できる

    const title     = "Good day!";
    const options   = {
        body : "It's a wonderful day!?",
        icon : "../Image/Icon/onsen64.png"
    };

    const notification = new Notification(title, options);

    notification.onclick = function(event) {
        console.log("クリックしましたね!");
    };

    notification.onshow = function(event) {
        console.log("表示しましたね!");
    };

    notification.onclose = function(event) {
        console.log("閉じましたね!");
    };

    notification.onerror = function(event) {
        console.log("エラーです!");
    };

onerrorは動作未確認。
onclick内でthrow "sample"を実行したけど発火しなかった。

おまけ、クリックイベント時のtimestampを得る

    notification.onclick = function(event) {
        console.log(new Date(this.timestamp));
    };

最初はoptionsdataプロパティにnew Date()を仕込んでいたけど、
console.log(this);の表示を見ていたらtimestampプロパティの存在に気づいた。
一部のブラウザでは未対応なので注意が必要か。

おまけ、雑記

  • dirプロパティは指定してみたが変化なし
  • silentプロパティはtrueにしたら通知音が消えた

参考

JavaScript, Notification APIを使ってトースト通知をする

はじめに

トースト通知(バナー通知)を使ってみたい。
C#でやってみたいが、少し調べてみたら面倒そうな印象を受けた(やるならUWPか・・・)。
他に試せるとしたらC#以外に触れている言語だとJavaScriptだ。
初めてのJavaScriptで少しトースト通知に触れた記憶があったのであらためて調べて試した。

動作環境

開発環境

トースト通知を表示するには?

Notificationオブジェクトを利用する。 MDNを見れば良いと思うんだ。

Notification APIは使えるか?

    if(window.Notification) {
        console.log("OK");
    }
    else {
        console.log("NG");
    }

通知の設定はどうなっているか?

    const permission = Notification.permission;

    if(permission === "default") {
        console.log("通知未設定");
    }
    else if(permission === "granted") {
        console.log("通知を許可した。");
    }
    else if(permission === "denied") {
        console.log("通知を拒否した。");
    }

まずは通知の設定を確認しdefaultdeniedならNotification.requestPermissionメソッドを使い、許可を得る。
許可を得ればgrantedになるので、あとはNotificationオブジェクトのインスタンスを作成すればトースト通知が使える。

通知の設定をするには?

    Notification.requestPermission((result) => {
        if(permission === "default") {
            console.log("通知未設定");
        }
        else if(permission === "granted") {
            console.log("通知を許可した。");
        }
        else if(permission === "denied") {
            console.log("通知を拒否した。");
        }
    });

「許可」ボタンを押すとgrantedとなり、トースト通知が使える。
「ブロック」ボタンを押すとdenied、「×」ボタンを押すとdefaultとなりトースト通知は使えない。
↓設定ダイアログ
f:id:HayaUp:20200418011038j:plain

トースト通知を表示する1、タイトルのみ

    const title         = "Good day!";
    const notification  = new Notification(title);

↓こうなる
f:id:HayaUp:20200418011146j:plain

トースト通知を表示する2、本文(サブタイトルっぽい)を追加

    const title         = "Good day!";
    const options       = { body : "It's a wonderful day!?" };
    const notification  = new Notification(title, options);

↓こうなる
f:id:HayaUp:20200418011212j:plain

トースト通知を表示する3、アイコンを追加

    const title         = "Good day!";
    const options       = {
        body : "It's a wonderful day!?",
        icon : "../Image/Icon/onsen.png"
    };
    const notification  = new Notification(title, options);

↓こうなる
f:id:HayaUp:20200418011225p:plain

iconは.jpgも表示できた。.svgは表示できなかった。
一応・・・options他にもプロパティがある。
※画像はICOOON-MONOさんにあるものを利用した。素敵な画像をありがとうございます!

おまけ1、iconに使う画像は最低でも64pxが良さそう

トースト通知を表示する3、アイコンを追加では32pxを利用したが若干ぼけている。
↓こちらは64px版。見比べてほしい。
f:id:HayaUp:20200418011245p:plain

おまけ2、半角文字だと1行は何文字分か?

34文字だった。
f:id:HayaUp:20200418011259j:plain

うっ、アイコンを設定したら30文字だった。
※bodyも同じ文字数だった。
f:id:HayaUp:20200418013758j:plain

おまけ3、全角文字だと1行は何文字分か?

18文字だった。
f:id:HayaUp:20200418011310j:plain

うぅ、アイコンを設定したら16文字だった。
※bodyも同じ文字数だった。
f:id:HayaUp:20200418013814j:plain

おまけ4、アイコンは何pxから大きくなるのか?

1pxから大きくなる..pngだからだろうか。
.icoなら違う結果かもしれない。

所感

JavaScriptなら簡単にトースト通知が扱えることが分かった。
IEとSafariでは対応していないので注意が必要か。

参考になりました!

C#, LINQのSumで複数のTimeSpanの合計を得る

はじめに

↓こんな感じでできると思っていた。

// LINQを使う
using System.Linq;

// 集計対象
var timespans = new[]
{
    new TimeSpan(0, 0, 1),
    new TimeSpan(0, 1, 0),
    new TimeSpan(1, 0, 0),
};

var total_time = timespans.Sum();

「TimeSpan[]には引数無しのSumの定義は無いですよ」(意訳)とVisual Studioさんが告げる。

こうします

var total_ticks = timespans.Sum(t => t.Ticks);
var total_time  = new TimeSpan(total_ticks);        // 01:01:01

おまけ?分単位や秒単位だといくつになるか?

var total_minutes = total_time.TotalMinutes;        // 61.016666666666666
var total_seconds = total_time.TotalSeconds;        // 3661

他にもTotalHoursTotalDaysTotalMillisecondsがある。便利だ。

おまけ?TimeSpanのインスタンス作成時の引数ticksに最大値を入れると・・・?

var max_timespan = new TimeSpan(long.MaxValue);

10675199.02:48:05.4775807になった。
ちなみにlong.MaxValue9223372036854775807
10675199は約29247年、遠大だ。
オーバーフローするとマイナスに転じるので注意しよう(発生しそうにない)。

雑記

小さく分けて書いてみた。こっちの方が良さげ。

補足

IDE

プロジェクト

  • コンソール アプリ(C#)
    • .NET Core 3.1

C#, LINQのGroupByで重複した要素と重複した要素が何個あるかを得る

はじめに

集計対象が複数のプロパティを持つオブジェクトの重複した要素と重複した要素が何個あるかが欲しくなった1
集計対象が1オブジェクト2の配列やコレクションだったらDistinctからのCountで済む。

ソースコード全文

using System;
using System.Linq;

namespace Sample
{
    class Program
    {
        static void Main(string[] args)
        {
            // 集計対象
            var Points = new[]
            {
                new { X = 0, Y = 0 },
                new { X = 0, Y = 1 },
                new { X = 0, Y = 1 },
                new { X = 1, Y = 0 },
                new { X = 1, Y = 0 },
                new { X = 1, Y = 0 },
                new { X = 1, Y = 1 },
                new { X = 1, Y = 1 },
                new { X = 1, Y = 1 },
                new { X = 1, Y = 1 },
            };

            // Method syntax
            // 1プロパティをグループ化
            var pointXs = Points.GroupBy(point => point.X);

            /*
                ↓表示結果
                0
                1
            */
            foreach(var pointX in pointXs)
            {
                Console.WriteLine(pointX.Key);
            }

            // 2プロパティをグループ化、おまけで重複したグループ数を得る
            var points = Points.GroupBy(point => new { point.X, point.Y })
                                .Select(point => new { point.Key.X, point.Key.Y, Count = point.Count() });

            /*
                ↓表示結果
                { X = 0, Y = 0, Count = 1 }
                { X = 0, Y = 1, Count = 2 }
                { X = 1, Y = 0, Count = 3 }
                { X = 1, Y = 1, Count = 4 }
            */
            foreach(var point in points)
            {
                Console.WriteLine(point);
            }

#if false
            // Query syntax
            var result = from pointXs in Points
                         group pointXs by pointXs.X;

            foreach(var item in result)
            {
                Console.WriteLine(item.Key);
            }

            var points = from pointXYs in Points
                         group pointXYs by new { pointXYs.X, pointXYs.Y } into point
                         select new { point.Key.X, point.Key.Y, Count = point.Count() };

            foreach(var point in points)
            {
                Console.WriteLine(point);
            }
#endif
        }
    }
}

所感

個人的にはメソッド構文の方がクエリー構文より使いやすい。
メソッド構文はクエリー構文より命名するオブジェクトの数が少なくて済むから。
※クエリー構文はSQLっぽく書けるから好きではあるが。
※何気にクエリー構文は行頭が揃うのが良い。上記のソースコードだとfromgroupselectの開始位置。

補足

IDE

プロジェクト

  • コンソール アプリ(C#)
    • .NET Core 3.1

書いた経緯など

SQLならパッと思いつくんだけどLINQは慣れていないので書き方が分からなかった。
また、調べるのも面倒なので備忘録として書き残した。
ついでにクエリー構文も調べて書いたけど、今後はメソッド構文だけを書くか。
載せるソースコードが長くなってしまう。


  1. 結局、使わなくてもよくなった・・・チーン

  2. intやstringなどオブジェクトのこと