Python の辞書に含まれる最大値のKeyを求めるクールな実装
下記のような辞書型があり、辞書の値の最大値を持つキーを取得したい。
例えば、下記のような辞書だ。
d = {'a': 1, 'b': 2, 'c': 3}
上記例では、 3 が最大値。よって、 c を得たい。
ここで if文のような条件分岐をつかった実装は クールではないのは容易に想像がつく。
ちなみに、最大値は、組み込み関数の max で取得できる。
>>> max(d.values()) 3
とやると、3 を取得することはできるが、そのキーはどうすれば取得できるだろう。
Python ではどのような実装がクールなのだろうか、とつぶやいたら RT され 一瞬で Reply をいくつかいただけた。
ありがたく、ご紹介させて頂く。
(一応、Python 2.7.5 を想定したのだが、明示しなかったので py3向けの回答もあったのかもしれない)
1. タプルにして最大値を求める実装
>>> max([(v,k) for k,v in d.items()])[1] 'c'
>>> max((v,k) for (k,v) in d.items())[1] 'c'
d.items() でタプルのペアを含むリストが取得できる。
>>> d.items() [('a', 1), ('c', 3), ('b', 2)]
最初の例は、リスト内包表記を用いリストにしそれを渡している。
2番目の例は、引数として複数のタプルを渡している。
いずれの例も、for文で内部のタプルを取り出し v (value)の最大値を求める。
最後の [1] を k を意味している。
max の仕様として、リスト(のようなiteratable)または複数の引数を受け付けるという仕様。Docstring を読む。
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
なお、Python 2系なら items の変わりに iteritems を使うと気持ち効率が良いらしい(未確認)
2. max のオプション引数 key を用いる実装 (itemgetter)
>>> from operator import itemgetter >>> max(d.items(), key=itemgetter(1))[0] 'c'
ここで maxの仕様 に目を通すと以下のような記載がある。
オプションの key 引数には list.sort() で使われるのと同じような 1 引数の順序付け関数を指定します。
Python 2.5以降で使える。 key= で関数を渡す。これを用いた実装だ。ここでは itemgetter() を使っている。
operator モジュールで提供されている。
>>> itemgetter(1)(("c",3)) >>> 3
ここでは、上記のように 1番目のタプルの要素を渡す関数となっている。
3. max のオプション引数 key を用いる実装 (lambda)
>>> max(d.items(), key=lambda x:x[1])[0] 'c'
lambdaを用い 配列要素の1番目を返却する無名関数を作成し、オプション引数に渡す実装。
これが一番シンプルな実装な気もする。
謝辞
Thanks to all Pythonistas!
- https://twitter.com/hamukazu/status/390278491947945985
- https://twitter.com/shota243/status/390278716967755777
- https://twitter.com/wonderful_panda/status/390277685307781120
- https://twitter.com/wonderful_panda/status/390286973903966208
- 作者: Tarek Ziade,稲田直哉,渋川よしき,清水川貴之,森本哲也
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2010/05/28
- メディア: 大型本
- 購入: 33人 クリック: 791回
- この商品を含むブログ (91件) を見る
WPF MVVM ふりかえり 発表資料
今年度から C#/WPF/MVVM/Prism な開発環境で過ごすことが多くなって来ました。私は実際の開発よりもCIやインストーラなどの役回りなのですが勉強しないといけないと思い、今日の mokusharp(木曜日 社内C#勉強会)で発表した資料になります。
発表資料(前編)
WPFとはなに? XAMLとは?MVVMとはと聞かれたときにいまいちイメージがつかめていなかったので、インターネットで参考になった有益な情報をまとめたガイドのような感じです。あくまで概要でざっと理解するためには役立つかと思います。
後編は?
後編としては、データバインディング、データテンプレート、コマンド、ビヘイビア を理解できる発表資料を行う予定です。
ackより速いagを試してみる
ackより速いらしいagを試してみました。ackはgrepをよりプログラマ向けに便利にしたもので、agはperlで記述されたackよりCで書いている分高速であることがウリとのことです。
インストール
debian GNU/Linux 7.0 wheezy 上で行います。Ubuntuでも同じ手順でインストールできます。
準備
$ sudo aptitude install automake pkg-config libpcre3-dev zlib1g-dev liblzma-dev
ビルド
$ git clone git://github.com/ggreer/the_silver_searcher.git $ cd the_silver_searcher $ ./build.sh $ sudo make install
debian 7 の Sphinx にて Could not import extension となる問題の原因と対策
debian 6 から 7.0 に upgrade したところ、sphinx の make html でエラーが出るようになってしまった。
Extension error
Extension error: Could not import extension sphinxcontrib.plantuml (exception: No module named plantuml) make: *** [html] エラー 1
調べてみると debian の pkg でインストールした場合に発生する現象である。
真の原因は果たしてなんであろうか、気になったので再現用のリポジトリを用意しました。
なお、ここでエラーとなっている extension はリポジトリ内に含めています。
正常時のログとエラーログ
https://gist.github.com/cointoss1973/268cb91ee21a4fb352ca
sys.path の環境変数の違いがなにか影響しているかと思われるが、果たして..
原因と対策
追記 2013/05/10
@cointoss1973 debian 側で入れてる、このパッチの影響だとおもいます。bit.ly/11oMwSC
— Tetsutaro KAWADAさん (@t3rkwd) 2013年5月10日
debian の sphinx パッケージにパッチがあたっており、 sphinxcontrib の名前がぶつかっているようです。 リポジトリ内の sphinxcontrib の名前を変えることで回避できそうですね。さてどんな名前にしようか...
ifconfig コマンドの導入
debian GNU/Linux 7.0 への ifconfig インストール方法のメモ。
インストール方法
$ sudo aptitude install net-tools
実行方法
/sbin なので通常のユーザではPATHが通っていないことに注意。
$ /sbin/ifconfig
インストールパスの確認方法
$ dpkg -L net-tools | grep ifconfig ... ... /sbin/ifconfig
local time から始めるプログラミング言語入門
プログラミング入門としては、Hello World を標準出力に出力することがよくあります。初めて触る言語で行うサンプルとして、Hello World より少しだけ進んで local time の現在時刻を表示するサンプルコードをいくつかつくってみました。
[2013/01/24 12:34:56] という現在時刻をメッセージやログに日付付きで記録したいときに役立つフォーマットです。
扱うプログラミング言語は、TIOBE で上位にランクされる人気の言語から C Java C++ C# Python Perl JavaScript Ruby とあと いくつかのプログラミング言語や環境で試してみます。
環境としては、主にWindows上で、いくつかMSYSで行なっています*1
C による実装
clock_gettime() を用います。time.h を include することで使用可能です。
#include <stdio.h> #include <time.h> #define TIME_MAXSIZE 64 void nowtime(char *str) { time_t timer = time(NULL); strftime(str, TIME_MAXSIZE, "[%Y/%m/%d %H:%M:%S]", localtime(&timer)); } int main() { char timestr[TIME_MAXSIZE]; nowtime(timestr); printf("%s\n", timestr); return 0; }
$ gcc -Wall time.c;./a
[2013/02/05 20:38:41]
Java による実装
Date 型で取得する関数 Date()があり、SimpleDateFormatクラスのformatメソッドで指定したString型に変換可能です。
import java.util.*; import java.text.*; public class NowTime { public static void main(String[] args){ System.out.println(getNowTime()); } static String getNowTime(){ Date now = new Date(); SimpleDateFormat fmt = new SimpleDateFormat("[YYYY/MM/dd HH:mm:ss]"); return fmt.format(now); } }
$ javac NowTime.java ; java NowTime
[2013/02/08 19:36:16]
C++ による実装
boost を用いてみたいと思います。ですが私の頭では Date_Time の仕様がよく理解できず、stackoverflow の回答をおもいっきり参考にさせて頂きました。
http://stackoverflow.com/questions/1904317/c-boost-date-with-format-dd-mm-yyyy
#include <iostream> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time_io.hpp> using namespace boost::posix_time; using namespace std; void nowtime(void) { time_facet *facet = new time_facet("[%Y/%m/%d %H:%M:%S]"); cout.imbue(locale(cout.getloc(), facet)); cout << second_clock::local_time() << endl; } #ifdef DEBUG int main(int argc, char **argv) { nowtime(); } #endif
$ g++ -Wall -I/usr/include/boost -DDEBUG nowtime.cpp ;./a
[2013/02/16 23:16:32]
C# による実装
DateTimeオブジェクトを取得し ToString で文字列に変換します。
using System; class Datetime { public static void Main() { Console.WriteLine(DateTime.Now.ToString("[yyyy/MM/dd HH:mm:ss]")); } }
Visual Studio コマンドプロンプトを開くことで、csc.exe(コンパイラ)にパスが通ります。
> csc nowtime.cs にてコンパイルを行いましょう。
> nowtime
[2013/02/23 22:28:45]
Python による実装
標準ライブラリ datetime が使いやすいです。import しましょう。
import datetime print datetime.datetime.today().strftime('[%Y/%m/%d %H:%M:%S]')
$python nowtime.py
[2013/01/24 21:25:11]
Perl による実装
localtime 関数にて現在の時刻を示す9個の時刻情報が返却されますので、書式を整えましょう。
#!/usr/bin/perl sub nowtime { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); my $date = sprintf("[%04d/%02d/%02d %02d:%02d:%02d]\n", $year+1900,$mon+1,$mday,$hour,$min,$sec); return $date; } print nowtime();
$ perl nowtime.pl
[2013/02/17 00:41:47]
JavaScript による実装
Dateオブジェクトにて現在時刻が取得できます。
var today = new Date(); var fmt = "["+ today.getFullYear()+"/"+today.getMonth()+1 +"/"+today.getDay()+" " +today.getHours()+":"+today.getMinutes()+":"+today.getSeconds()+"]" WScript.echo(fmt);
Windows 上で explorer nowtime.js という形で起動します(またはnowtime.js ファイル)をダブルクリックします。
Ruby による実装
#!/usr/bin/env ruby def nowtime return Time.now.strftime("[%Y-%m-%d %H:%M:%S]") end puts nowtime
$ ruby nowtime.rb
[2013-02-17 01:36:04]
bash による実装
date コマンド(GNU date) に頼ることにします。
echo "["`date +"%Y/%m/%d %k:%M:%S"`"]"
[2013/01/24 20:24:25]
Windows Power Shell による実装
Get-Date コマンドレットを使用します。
PS C:\> Get-Date -format ["yyyy/MM/dd hh:mm:ss"]
[2013/04/09 12:13:36]
Emacs Lisp による実装
M-x にて ielm にてインタラクティブシェルを起動します。
(スクラッチバッファにて C-j でも実行することができます)
ELISP> (format-time-string "[%Y/%m/%d %H:%M:%S]" (current-time)) "[2013/03/01 10:50:44]"
さいごに
表示された日付時刻がまちまちなのは、それぞれのプログラミング言語で実装した時刻の差です。いろいろな言語を気長に試した結果なので気にしないでくださいね。
追記。その他いくつかの言語による実装を行われた方がいましたのでリンクをご紹介します。