くりーむわーかー

プログラムとか。作ってて ・試しててハマった事など。誰かのお役に立てば幸いかと。 その他、いろいろエトセトラ。。。

オブジェクト

Python 内包表記まとめ

完全にメモ。

import random,string,time
from operator import itemgetter, attrgetter

def randomname(n):
   return ''.join(random.choices(string.ascii_letters + string.digits, k=n))

class SampleClass:
    def __init__(self,name,val,hoge):
        self.name = name
        self.val = val
        self.hoge = hoge

# 単純なList
numl = [random.randint(1, 1000) for i in range(100)]
selected = [v for v in numl if v < 500]
print(selected)

# 辞書
dicl = [{"key": randomname(5),"val":random.randint(1, 1000)} for i in range(100)]
selected = [v for v in dicl if v["val"] < 500]
print(selected)

# 辞書から特定要素の配列を作る
dicl = [{"key": randomname(5),"val":random.randint(1, 1000)} for i in range(100)]
selected = [v["key"] for v in dicl if v["val"] < 500]
print(selected)

# タプル
tupl = [(randomname(5),random.randint(1, 100), random.randint(200, 300) ,) for i in range(100)]
selected = [v for v in tupl if v[1] < 50]
print(selected)

# タプルのリストから部分的な要素にしたタプルのリストにする
tupl = [(randomname(5),random.randint(1, 100), random.randint(200, 300) ,) for i in range(100)]
selected = [(v[0],v[2],) for v in tupl if v[1] < 50]
print(selected)

# オブジェクトから特定フィールドのタプルにしつつ、リストにする
objl = [SampleClass(randomname(5),random.randint(1, 100),random.randint(200, 500)) for i in range(100)]
selected = [attrgetter("name","hoge")(v) for v in objl if v.val < 50]
print(selected)

Python Listのソートまとめ

list.sort()と sorted(list)の 2 つ。

まずは → を読むべし。https://docs.python.org/ja/3/howto/sorting.html

オブジェクトの配列をソートするとかする場合はkey関数を使う。

性能とか

import random
import time

time_sta = time.perf_counter()
for i in range(10000):
    numl = [random.randint(1, 1000) for i in range(100)]
    numl.sort()
time_end = time.perf_counter()
tspan = time_end- time_sta
print(tspan)

time_sta = time.perf_counter()
for i in range(10000):
    numl = [random.randint(1, 1000) for i in range(100)]
    sorted(numl)
time_end = time.perf_counter()
tspan = time_end- time_sta
print(tspan)

# どっちも大差無
3.690590940999982
3.6823944669999946

昇順/降順

numl = [random.randint(1, 1000) for i in range(100)]
print(numl.sort(reverse=True))
print(sorted(numl, reverse=True))

両者の違い

numl = [random.randint(1, 1000) for i in range(10)]
print(numl)
print(numl.sort())
print(numl)

[746, 897, 3, 989, 2, 216, 666, 852, 387, 409]
None
[2, 3, 216, 387, 409, 666, 746, 852, 897, 989]

numl = [random.randint(1, 1000) for i in range(10)]
print(numl)
print(sorted(numl))
print(numl)

[931, 793, 220, 503, 827, 961, 114, 530, 30, 528]
[30, 114, 220, 503, 528, 530, 793, 827, 931, 961]
[931, 793, 220, 503, 827, 961, 114, 530, 30, 528]

`list.sort()`は破壊的

`sorted(list)`は非破壊的

で、基本的には`sorted()`を使った方が良さそう。

Key 関数の使い方と性能

使い方
import random,string,time
from operator import itemgetter, attrgetter

dicl = [{"key": randomname(5),"val":random.randint(1, 1000)} for i in range(5)]

print( sorted(dicl,key=lambda x:x["key"]) )
print( sorted(dicl,key=lambda x:x["val"]) )

print( sorted(dicl,key=itemgetter("key")) )
print( sorted(dicl,key=itemgetter("val")) )
性能
import random,string,time
from operator import itemgetter, attrgetter

dicl = [{"key": randomname(5),"val":random.randint(1, 1000)} for i in range(1000)]
time_sta = time.perf_counter()
for i in range(10000):
    sorted(dicl,key=lambda x:x["key"])
time_end = time.perf_counter()
tspan = time_end- time_sta
print(tspan)

time_sta = time.perf_counter()
for i in range(10000):
    sorted(dicl,key=itemgetter("key"))
time_end = time.perf_counter()
tspan = time_end- time_sta
print(tspan)

7.373934460000328
6.795032753000214

`itemgetter` 使いましょう。

色んなデータ構造でソート

# 単純なList
numl = [random.randint(1, 1000) for i in range(5)]
print(sorted(numl))
print(sorted(numl,reverse=True))

# 辞書
dicl = [{"key": randomname(5),"val":random.randint(1, 1000)} for i in range(5)]
print(sorted(dicl,key=itemgetter("key")))
print(sorted(dicl,key=itemgetter("val"),reverse=True))
print(sorted(dicl,key=itemgetter("val","key")))# 複数キーのソート

# タプル
tupl = [(randomname(5),random.randint(1, 100), random.randint(200, 300) ,) for i in range(5)]
print(sorted(tupl,key=itemgetter(0)))
print(sorted(tupl,key=itemgetter(2),reverse=True))
print(sorted(tupl,key=itemgetter(2,0)))# 複数キーのソート

# オブジェクト
objl = [SampleClass(randomname(5),random.randint(1, 100)) for i in range(5)]
print(sorted(objl,key=attrgetter("name")))
print(sorted(objl,key=attrgetter("val"),reverse=True))
print(sorted(objl,key=attrgetter("val","name")))# 複数キーのソート

class SampleClass:
    def __init__(self,name,val):
        self.name = name
        self.val = val

javascript D3使って集計とか

D3使ってオブジェクト内の集計をやりたくなった。ちょっとだけ複雑なオブジェクトでやりたい。 例えば下くらいのオブジェクトの配列で。

var hogeobj= {
    date: "2016-04-01",
    group: {
        classname: "都道府県",
        values: [
            { name1: "青森", name2: "りんご", value: 6 },
            { name1: "秋田", name2: "美人", value: 10 },
            { name1: "秋田", name2: "きりたんぽ", value: 2 },
            { name1: "宮城", name2: "笹かま", value: 3 },
            { name1: "青森", name2: "りんご", value: 8 },
            { name1: "青森", name2: "美人", value: 4 },
            { name1: "秋田", name2: "笹かま", value: 15 },
            { name1: "宮城", name2: "桜", value: 1 },
        ]
    }
}

上の感じのデータセットで、例えば、各オブジェクト内のname1のグループ毎にvalueを合計したいとか。下の感じ。

var groupCountObj = d3.nest()
                            .key(function (d) { return d.name1; })
                            .rollup(function (v) { return d3.sum(v, function (d) { return +d.value; }); })
                            .map(hogeobj.group.values);
console.log(groupCountObj);
->Object {青森: 18, 秋田: 27, 宮城: 4}

集計はされるんだけど、Objectで結果が戻ってくるので割と扱いにくい。なので、配列にkey-value的な感じでmapする。

var tmpob = $.map(groupCountObj, function (value, index) {
    return { label: index, value: value }
});
console.log(tmpob);
->[Object, Object, Object]
0:Object
label:"青森"
value:18
__proto__:Object

1:Object
label:"秋田"
value:27
__proto__:Object

2:Object
label:"宮城"
value:4
__proto__:Object

length:3
__proto__:Array[0]

これでD3使っての円グラフとかに使いやすくなる。

久しぶりにD3使ったけど、すごい忘れてる。。。えらいこっちゃ。

問合せ