ざっくりん雑記

プログラミングで忘れそうなことをひたすらメモる

Ruby - 配列やハッシュの繰り返し each

配列の要素をいい感じに取り出して利用する

eachメソッドは「イテレータ」という種類のメソッドで、以下のような構文

配列.each do |変数|
    繰り返したい処理
end

または

配列.each{|変数|}
    繰り返したい処理
end

最初の例では、each以降のdo ~ endの部分はブロックと呼ばれる部分で、こういった構文のため一般にブロック付きメソッドとも呼ばれる。ふたつ目の例はdoを省略したかたちで、基本的にこちらほうが見やすそう。

|変数|という部分では、配列から1つずつ取りだす際に使う変数名を指定することができる。その変数をブロック内で利用することになる。なのでわかりやすい命名をしたい。

基本的な使い方の例

基本は配列もハッシュも同じような構文で、ハッシュの場合は変数を2つ設定できる。以下にハッシュの場合を示す。

neta = {
    :maguro => 'まぐろ',
    :salmon => 'サーモン',
    :tamago => 'たまご'
}

neta.each do |key, value|
    puts "#{key}:#{value}"
end
$ruby array_prac.rb
maguro:まぐろ
salmon:サーモン
tamago:たまご

いろんな使い方

ブロック的に使わないでかんたんに書きたいとき

neta.each{|en, ja| puts "#{en}を日本語で, #{ja}と言う!"}
$ruby array_prac.rb
tunaを日本語で, まぐろと言う!
salmonを日本語で, サーモンと言う!
eggを日本語で, たまごと言う!

ハッシュの深さがある場合

変数指定に括弧を使えば、いい感じにやってくれる。

neta = {
    :tuna => ['まぐろ', 100],
    :salmon => ['サーモン', 200],
    :egg => ['たまご', 300]
}

neta.each{|id, (name, price)| puts "#{id}: #{name}, #{price}"}
$ruby array_prac.rb
tuna: まぐろ, 100
salmon: サーモン, 200
egg: たまご, 300

参考

たのしいRuby 第5版

たのしいRuby 第5版

qiita.com

PHP - print_r()とvar_dump()について

print_r()var_dump()は、渡された内容を見やすい形式で出力する。文字列や数値の場合はecho, print()と同様に単純に文字列として出力する。

配列の場合は、以下のように出力する。

<?php

$a = array('name' => 'azunobu', 'age' => 20, 'location' => 'Iwate');
print_r($a);
var_dump($a);

出力

Array
(
    [name] => azunobu
    [age] => 20
    [location] => Iwate
)

array(3) {
  ["name"]=>
  string(7) "azunobu"
  ["age"]=>
  int(20)
  ["location"]=>
  string(5) "Iwate"
}

オブジェクトの場合は、以下のように出力する。

<?php
class Sample {
    var $name = 'azunobu';
}

$o = new Sample;
print_r($o);
var_dump($o);

出力

Sample Object
(
    [name] => azunobu
)

object(Sample)#1 (1) {
  ["name"]=>
  string(7) "azunobu"
}

print_r()とvar_dump()の違い

まず、print_r()論理値やNULLだとうまく表示してくれない。

print_r(true);    // "1"を出力
print_r(false);    // ""を出力
print_r(null);    // ""を出力

一方、var_dump()は、論理値やNULLであっても表示してくれる。

var_dump(true);    // "bool(true)"と出力
var_dump(false);    // "bool(false)"と出力
var_dump(null);    // "bool(null)"と出力

以上のことから、デバッグ時に使うとすれば、人間的に読みやすい形式で出力してくれるvar_dump()のが使い勝手が良さそう。

なお、出力された値をブラウザで確認する際は、ソースを見たほうが改行がうまく効いて見やすい。Chromeであればページの適当なところを右クリックし ページのソースを表示で表示できる。

参考

プログラミングPHP 第3版

プログラミングPHP 第3版

PHP - ヒアドキュメント

複数行にまたがる文字列を出力したいとすると、文字列を連結したり、以下のように

<?php

echo '照りつける 太陽 照り焼けちまいそう\n';
echo 'ハードボイルドだろ? パネェだろ?\n';
echo 'キモい カワイイ 賛否両論 NO MORE WAR\n';
...

echoしまくる感じになるが、ちょっと面倒くさい。

ヒアドキュメントを使う

ヒアドキュメントを用いれば、複数行にまたがる文字列を手軽に書ける。

$str = <<< "EndOfQuote"
照りつける 太陽 照り焼けちまいそう
ハードボイルドだろ? パネェだろ?
キモい カワイイ 賛否両論 NO MORE WAR
サブカル 女子 凝視 酢飯飛び散る
Let's go to the animation
寿司くん!
EndOfQuote;

var_dump($str);

出力

string(260) "照りつける 太陽 照り焼けちまいそう
ハードボイルドだろ? パネェだろ?
キモい カワイイ 賛否両論 NO MORE WAR
サブカル 女子 凝視 酢飯飛び散る
Let's go to the animation
寿司くん!
"

改行も含まれている。

<?php

printf(<<< "Template"
%s is %s.
Template
, "寿司くん", "Sushi");

出力

寿司くん is Sushi.

書き方

<<< [識別子]というトークンが、ヒアドキュメントの開始を示す。 <<<[識別子]の間には半角スペースが1つ必要。文字列を書き終えたら、改行し識別子を示すことで、文字列の終端を示す。

また、PHP 5.3.0 以降では、ヒアドキュメントの宣言をダブルクォートで囲めるようになった。

ダブルクォーテーション、シングルクォーテーション、空白などが素直に出力される。

寿司くん

参考

プログラミングPHP 第3版

プログラミングPHP 第3版

PHP: 文字列 - Manual

PHP - 関数のパラメータ

関数を定義するとき、任意の値を引数(パラメータ)として渡すことができる。

渡す方法として、値渡し参照渡しがある。

値渡しのパラメータ

大抵の場合は、こちらを使う。引数には任意の式を指定でき、式の内容が評価された後の値が関数に渡される。

<?php

function greeting($name) {
    echo $name."さん。おはよう。";
}

$name = "azunobu";
greeting($name);

例として、こういったかたちで書ける。

参照渡しのパラメータ

参照渡しでは、通常のスコープの規則を無視し、関数内から直接変数の値を操作する。そのため、参照渡しではパラメータとして変数を渡す必要がある。 参照で渡す、ということを明示するには関数のパラメータリストの引数名の前にアンパサンド記号(&)を付ける。

<?php

function greeting(&$personName) {
    echo $personName."さん。おはよう。";
}

$name = "azunobu";
greeting($name);

この例では、関数内の$personNameは参照渡しで渡されているので、直接$nameを参照している。 そのため、値の変更も関数内で直接変更を加えることができる。

また、参照渡しの主な恩恵としては、変数をコピーする必要がない。PHPでは、値渡しを行うと関数を実行する前に値の内容のコピーを作成する必要がある。 長い文字列や大きなオブジェクトの場合、このコピーは大きなコストになり実行速度にも影響を与えかねない。 参照渡しはこの点、コピーをせず直接参照できるため有利。

可変パラメータ

関数のパラメータの数を可変にしたい、という時もある。 PHP5.6以降であれば、パラメータリストに ... トークンを含めることで、 その関数が可変長の引数を受け取ることを示すことができる。

<?php

function sum(...$numbers) {
    $total = 0;
    foreach ($numbers as $num) {
        $total += $num;
    }
    return $total;
}

echo sum(1, 2, 3, 4, 5, 6, 7, 8, 9);

出力結果は45となる。

タイプヒンティング

渡ってきたパラメータが特定のクラス(あるいは特定のクラスを継承したクラス)のインスタンスであるか?コールバック関数であるか?…というバリデーション的なことが可能。

この部分の説明に関しては、とても分かりやすく解説された記事があるため、こちらを紹介します。

dekokun.github.io

参考

プログラミングPHP 第3版

プログラミングPHP 第3版

PHP: ユーザー定義関数 - Manual

PHP: 関数の引数 - Manual

PHPでコールバック関数を利用する - Qiita

PHP - キャスト演算子

値を特定の型として扱いたい

PHPは元々、弱い型付けの言語であるが、特定の型として扱いたい場面もある。 そういった時は以下のキャスト演算子でキャストすることも可能。

PHPのキャスト演算子

演算子 同じ意味の演算子 変更後の型
(int) (integer) 整数
(bool) (boolean) 論理値
(float) (double), (real) 浮動小数点数
(string) 文字列
(array) 配列
(object) オブジェクト
(unset) NULL

(string) に関してはstrval()関数と同様。

参考

プログラミングPHP 第3版

プログラミングPHP 第3版

PHP (PDO) - Unknown character set

PDOクラスにおいてのDB接続時エラー

define('DSN', 'mysql:host=localhost;dbname=hoge;charset=utf-8;');
define('USER', 'piyouser');
define('PASSWORD', '1234');

try {
    $dbh = new PDO(DSN, USER, PASSWORD);
    echo '接続に成功しました。'.'<br>';
} catch (PDOException $e) {
    echo $e->getMessage();
    exit;
}

エラー:SQLSTATE[HY000] [2019] Unknown character set

MySQLに対してのcharsetはutf-8ではなくutf8です。 HTMLを書いているとcharset=utf-8なので、その辺と混同して間違いやすいですね。 気をつけよう。

参考

PHP - データ型

 ざっくり、PHPには8種類のデータ型がある。

  • スカラー型(単一の値を取る)
  • 複合型(コレクション)
    • 配列
    • オブジェクト
  • 特殊型
    • リソース
    • NULL

整数

  • 10進形式、8進形式、16進形式そして2進形式の4通り

10進形式

2016
-321
+321

8進形式

8進数と見なされるには

  • 先頭が0
  • その後、0から7までの数字で続ける

とする。プラス・マイナスといった符号が付けられる。

0755         # 10進形式だと493
+010         # 10進形式だと8

16進形式

16進数と見なされるには

  • 先頭が0x
  • その後に数字(0,1)あるいは英字(AからF)で続ける

とする。英字は小文字/大文字は問わない。通常は大文字。符号付けられる。

0xFF         # 10進形式だと255
0x10         # 10進形式だと16
-0xDAD1      # 10進形式だと-56017

2進形式

2進数と見なされるには

  • 先頭が0b
  • その後に数字(0,1)で続ける

とする。符号付けられる。

0b00000001         # 10進形式だと1
0b00000010         # 10進形式だと2
-0b10              # 10進形式だと-2

その他

  • 整数値の範囲を超えた場合、数値以外を代入しようとした場合、自動的に浮動小数点への変換が行われる
  • 整数値かどうか調べる
if (is_int($number)) {
    // $numberは整数
}

浮動小数点数

PHPでの浮動小数点数の表し方

  • 普段見慣れている形式
3.14
0.00211
-432.122
  • 科学で用いられる記法
0.314E1     # 0.314*10^1 -> 3.14
17.0E-3     # 17.0*10^(-3) -> 0.017

浮動小数点数はあくまでも近似値

まず、注意したいのは、浮動小数点数どうしを比較する(==)コードは書いてはいけないこと。

たとえば「5.5」という値、多くのシステム上では「5.499999999999」という値で表されている。浮動小数点数が正確な値であると、期待してはいけない。

じゃあ、どう比較すればいいの? -> 小数点以下の特定桁数までのみで比較しよう

例として小数点以下3桁までを対象として比較するコードを示す。

if (intval($number_a * 1000) == intval($number_b * 1000)) {
    // 小数点以下3桁までは共通
}

その他

if (is_float($number)) {
    // $numberは浮動小数点数
}

文字列

 PHPは、Webで用いられる言語として多くの文字列操作機能を標準で組み込んでいる。  文字列とは、任意の長さの文字列を連結したもので、文字列リテラルを表すには、シングルクォート(')ダブルクォート(")で囲む。

  • ダブルクォート
    • その内部の変数は展開される
  • シングルクォート
    • 内部に変数があっても展開されない
$sushi = "maguro";
echo "Ah, I want to eat $sushi\n"
echo 'Ah, I want to eat $sushi'

上記を実行すると

Ah, I want to eat maguro
Ah, I want to eat $sushi

という結果になり、シングルクォートの変数は展開されないことがわかる。

2つの文字列が等しいかどうか

比較演算子 == を用いる。

if ($a == $b) {
  echo "aとbは等しい"
}

ある値が文字列であるかどうか

is_string()関数を用いる。

if (is_string($string)) {
  echo "$string は 文字列です"
}

その他

文字列はその他、多くの関数があるが、ここではひとまず触れないこととする。

論理値

 論理値とは、何かが真か偽かを表す。以下のように条件指定で調べる。

if ($alive) { ... }

PHPでfalse(偽)であるとみなされるもの

  • 整数値0
  • 浮動小数点数0.0
  • 空の文字列("")および文字列"0"
  • 素数がゼロの配列
  • プロパティやメソッドを一切持たないオブジェクト
  • NULL

逆に言えば、以上のもの以外はすべてtrueである。

ある値が論理値かどうか調べる

  • is_bool()関数を用いる。
if (is_bool($a)) {
    // $aは論理値
}

配列

 配列は、いくつかの値を一括して管理する。個々の値はゼロから始まる番号、あるいは文字列を指定して取得する。

$sushi[0] = "maguro";
$sushi[1] = "salmon";
$sushi[2] = "egg";

$favorability['maguro'] = "めっちゃ好き";
$favorability['salmon'] = "わりと好き";
$favorability['egg'] = "嫌いじゃない";

 array()構文にて作成する。

$sushi = array("maguro", "salmon", "egg");
$favorability = arrya('maguro'     => "めっちゃ好き",
               'salmon'     => "わりと好き",
               'egg'        => "嫌いじゃない");

 個々の値を処理する方法はいろいろある。最もよく使われているのはforeachループ。

foreach ($sushi as $neta) {
  echo "I like {$neta}\n";
}

foreach ($favorability as $neta => $rate) {
  echo "{$neta} はどれくらい好き勝手言うと… {$rate}かな?\n";
}

 上のコードが実行されると、以下の様な出力がされる。

I like maguro
I like salmon
I like egg
maguro はどれくらい好きかという… めっちゃ好きかな?
salmon はどれくらい好きかという… わりと好きかな?
egg はどれくらい好きかという… 嫌いじゃないかな?

 という感じ。

ある値が配列かどうか調べる

  • is_array()関数を用いる。
if (is_array($x)) {
    // $xは配列
}

その他

このような関数以外にも要素をソートする関数、要素数を数える関数など配列を操作する関数は数多くある。

オブジェクト

 PHPでは、オブジェクト指向プログラミングをサポートしている。クラスとは、オブジェクト指向設計で用いられる一つの部品であり、プロパティ(変数)やメソッド(関数)を持つ構造体のようなものである。クラスの定義はclassで行う。

class Sushi
{
    public $name = '';

    function name ($newname = NULL)
    {
        if (!is_null($newname)) {
            $this->name = $newname;
        }

        return $this->name;
    } 
}

 一度クラスを定義すれば、newキーワードを用いていくつでもそのオブジェクトを生成することができる。オブジェクトのプロパティやメソッドにアクセスする際には、->を用いる。

$maguro = new Sushi;
$maguro->name('まぐろ');
echo "めっちゃ新鮮な、 {maguro->name}\n";
$salmon = new Sushi;
$salmon->name('サーモン');
echo "めっちゃ新鮮な、 {salmon->name}\n";
めっちゃ新鮮な、 まぐろ
めっちゃ新鮮な、 サーモン

ある値がオブジェクトかどうか調べる

  • is_object()関数を用いる。
if (is_object($x)) {
    // $xはオブジェクト
}

リソース

 多くのモジュールには、PHPの外部の世界とやり取りするための関数が用意されている。  データベース関連の拡張モジュールであれば、

  • データベースへの接続
  • クエリの送信
  • データベースとの接続解除

 といったようなメソッドがある。  一度に複数のデータベース接続を扱うこともあるため、接続用関数は、確立した一意な接続を表す識別子を返すようになっている。この識別子を、リソース(またはハンドル)という。  アクティブなリソースは、各々が一意な識別子をもつ。その識別子は数値のインデックスとなっている。

 PHPの内部ルックアップテーブルはこのリソースを保持し、参照することになっている。コード内でそのリソースが参照されている(使用されている)数などを、このテーブルで管理する。作成したリソースへの参照がなくなった時点で、そのリソースを作成した拡張モジュール自身がメモリの解放などの後始末を行う。

 関数内でリソースをローカル変数に代入してしまえば、関数が終了した時点でそのローカル変数への参照はなくなる、つまりその変数の値がPHPの管理下に戻るため、後始末が自動的に実行させることができる。

 多くの拡張モジュールでは、後始末用の関数を個別で用意しているため、自動的なリソース解放に頼らずとも、明示的にその関数を呼び出すことでリソースを開放することも可能であったりする。

ある値がリソースかどうか調べる

  • is_resource()関数を用いる。
if (is_resource($x)) {
    // $xはリソース
}

NULL

 NULLが表す値は1つだけ、NULLである。これは、大文字/小文字を区別しない。  NULLということは、その変数に何も値が代入されていないことを表す。(PerlPythonでいうNoneと同じ意味)

$sushi = "maguro";
$sushi = "null";    // 変数の値が解除
$sushi = "Null";    // 上と同じ
$sushi = "NULL";    // 上と同じ

ある値がNULLかどうか調べる

  • is_null()関数を用いる。
if (is_null($x)) {
    // $xはNULL
}

参考

プログラミングPHP 第3版

プログラミングPHP 第3版