多次元配列の要素を特定の値をキーとしてマージする

2015/8/25

FuelPHPのArrクラスでは、非常に便利な配列操作のヘルパー関数が用意されているのですが、ありそうでなかったので…

それから、記事タイトルが何言ってるのか正直自分もよく分からないので例を。

array(
    array(
        'group' => 'CV1',
        'name' => 'Miku'
    ),
    array(
        'group' => 'CV2',
        'name' => 'Rin'
    ),
    array(
        'group' => 'CV2',
        'name' => 'Len'
    )
);

のような入力を与えた時に、

array(
    'CV1' => array(
        array(
            'group' => 'CV1',
            'name' => 'Miku'
        )
    ),
    'CV2' => array(
        array(
            'group' => 'CV2',
            'name' => 'Rin'
        ),
        array(
            'group' => 'CV2',
            'name' => 'Len'
        )
    )
);

あるいは、

array(
    'CV1' => array(
        'Miku'
    ),
    'CV2' => array(
        'Rin',
        'Len'
    )
);

のような出力を得たい、ということです。あるキーの同じ値同士でまとめるような感覚でしょうか。

とりあえず以下のように書いてみました。

class Arr extends \Fuel\Core\Arr
{
	/**
	 * @param array  $assoc     変換する配列
	 * @param string $key_field keyとなる連想配列の添字
	 * @param string $val_field valueとなる連想配列の添字
	 * @return array
	 */
	public static function merge_assoc_key($assoc, $key_field, $val_field = null)
	{
		$output = array_fill_keys(array_column($assoc, $key_field, $key_field), array());

		foreach ($assoc as $elm)
		{
			array_push($output[$elm[$key_field]], $val_field ? $elm[$val_field] : $elm);
		}

		return $output;
	}
}

パフォーマンスがどうか全く分からんですけど、

Arr::merge_assoc_key($input, 'group');
Arr::merge_assoc_key($input, 'group', 'name');

みたいな感じで、期待した結果が得られます。

データベースから取ってきた配列をこんな感じで整形したいことがそこそこある気がします、よね?

書いてて思ったけど、PHPには豊富な配列操作の標準関数が用意されるけども、マニュアルを眺めてあーこれこれ、こんなんあったね、とかやってるあたりまだ未熟だなぁ…

Windows 10 x64 + AMD Radeon でNetBeansがクラッシュする

2015/8/24

昨日、Windows 8.1 x64 なメインPCをWindows 10 Pro x64へアップグレードしました。
不具合があると困ってしまう開発環境周りは事前に検証をしていたのですが、実際アップグレードしてみるとハードが絡んだ問題が発生してしまったので書いておきます。
ちなみに発生条件は他に同様の報告も見当たらず詳しく調査していないので、記事タイトルにあるもの以外の要因があるかもしれません。


対象のソフトウェアはNetBeans 8.0.2
正常に起動するものの、しばらく操作していると突然クラッシュしてしまう現象が発生しました。
特定のアクションで発生するわけでもなく、ランダムに発生する感じでした。

まず、検証を行った環境と異なる点といえば、JDKを8u60に更新したので、以前発生したJava SE 8u20の不具合のような問題があるのではないかと考え、8u51にダウングレードしてみたものの症状は解決せず。

JVMのログを見てみると、

# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff9813122bf, pid=5428, tid=8140
#
# JRE version: Java(TM) SE Runtime Environment (8.0_60-b27) (build 1.8.0_60-b27)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [atig6txx.dll+0x122bf]

とあり、グラフィック周りが怪しげです。
確かに、検証用のPCではIntel HD Graphicsでしたが、メインPCはRadeon R7 250Xを搭載している点が異なっています。

さらにアップグレード後に、グラフィックドライバをCatalyst 15.7.1に更新しており、これが原因ではないか?
ということで、Windows 8.1の時と同じ、一つ古いCatalyst 15.7をインストールし直してみましたが、解決せず。
さらに古いCatalyst 14.12も試してみましたが、これもダメでした。

半分諦めながら、色々ググっていると、以下のようなページを発見。

Chatty Help – Troubleshooting: http://getchatty.sourceforge.net/help-issues.html

Java Crash: Graphics Driver

Solution/Workaround
Seems to have to do with the graphics driver. Reinstalling/updating the graphics driver may help or using the following commandline parameter, which should disable the calls to the library that cause the error:

-Dsun.awt.nopixfmt=true

詳しくはわかりませんが、ここら辺見てみるとddraw.dllをロードしないようにするパラメータらしいです。

<installation folder>\etc\netbeans.conf の netbeans_default_options 
-J-Dsun.awt.nopixfmt=true」 を追加してみました。
すると、しばらく使ってみてもクラッシュしなくなったようです!
とりあえずこのパラメータで回避できるみたいです。