Xamarinでのエラー

foramsでつくったプロジェクトでエラーが頻発しているのでその記録。

最初ファイルパッケージほにゃららが存在しません(パッケージは存在する)というエラーが頻出していたが、これはどうもXamarin.Androidが、Android SDK Build-tools Version 24に対応していなかったために起こっていたようなのでversion24関連を全部アンインストールすることで解消。

  1. Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCompat.Light.DarkActionBar'.
  2. No resource found that matches the given name: attr 'colorAccent'.
  3. No resource found that matches the given name: attr 'colorPrimary'.
  4. No resource found that matches the given name: attr 'colorPrimaryDark'.
  5. No resource found that matches the given name: attr 'windowActionBar'.
  6. No resource found that matches the given name: attr 'windowActionModeOverlay'.
  7. No resource found that matches the given name: attr 'windowNoTitle'.
  8. Error retrieving parent for item: No resource found that matches the given name 'Theme.AppCompat.Light.Dialog'.
  9. No resource found that matches the given name: attr 'colorAccent'.

↑特に何もいじっていない、デフォルトのプロジェクトを展開したはずなのにビルドできずエラーが出る。1、8に関してはソースの該当箇所をparent="android:Theme.Light"と別のものに置き換えることで解決。2〜7、9についてはコードに原因があるのかと思いきや今度はSDKBuild-toolsのversion23が入っていることで起こっているんじゃないかと議論しているので(Issue 183122 - android - Error retrieving parent for Item - AppCompact-v7 23 - Android Open Source Project - Issue Tracker - Google Project Hosting)、version23をアンインストールすることで解決した。

全部解決したかと思いきやバージョンが古くなりすぎたのか'Android SDK Build-tools' is in use which this version of Android Support Library does not support.と言われYou also need to install 'Android SDK Build-tools' version 23.0.0 or higher.とも言われたのでとりあえず23、24以外でversion25.00を入れたもののdoes not supportと言われいったんどうしようか考え中。SDKをインストールしたりアンインストールしたりする以外の解決方法があればそのほうがいいのかもしれないが……。

またリビルドすると大量にPlease install package: 'Xamarin.Android.Support.v7.RecyclerView'系の必要パッケージをインストールしてくださいというエラーが20以上出るが、すべてデフォルトで入っているので何がなんだかわからない。最新のバージョンでないのは確かで、パッケージ(Android.support系)を更新することで直りますよというQ&Aの結果が一番多いので一番最初に試してみたのだが、相互に依存関係のあるパッケージ間でバージョン差が発生するために更新できませんというエラーが出て更新できず対応方法を検討中。もしくはSDKで必要な物がダウンロードされていないのかと思ったが、extras含め一通り入れているので確認する。

↑追記。Please install package系のエラーはどうも最初のパッケージインストールが不完全に終わってしまっていたから発生していたもののようで、いったんすべて削除して再度ビルドしたことできれいに解消されたので、あと解決が必要にみえるのはSDK周りのエラーのみになった。

RubyでのJSON周りの話

基本JSON周りの話(csv,tsvからjsonへの変換、その逆などなど)

hash = File.open("meibo2.json") do |file|
  JSON.load(file)
end

jsonファイル読み込みの基本形(読み込んでハッシュに変換する)。取得した値に対して、タブなりなんなりでjoinして出力する際には基本は項目を明示的に指定してやる必要があるのはちょっとハマった(=hash.values で得られるvaluesは順不同で値が返ってくる可能性があるため)。たとえば⇛key["name"] + "\t" + key["gender"] + "\t" +key["age"] こんな感じの指定で。

jsonファイルのオープンについては一行で『hash = JSON.parse(File.read("honya.json"))』のように書くことも可能だが、例外時の原因がわかりづいらのでファイルが明示的に指定できる時とか用か。

csv,tsvからJSONへの変換は基本ファイルオープン、要素分割、key値ごとに値を入れてpretty_generateメソッドもしくはgenerateで出力するところまででワンセットか。下記はその一例

CSV.foreach('latlon.csv') do |csv|
    hash = {
      "lat" => csv[0],
      "lon" => csv[1]
    }
    pp hash
    csv_ary.push hash
end

File.open("latlon.json", "w") do |latjson|
  latjson.puts JSON.pretty_generate(csv_ary)
end

Rubyでの時刻操作

Rubyでの時刻操作まとめ

  • 基本的にTimeでもDateTimeでもローカルタイムの時刻をとってきてくれるが、明示的にタイムゾーンを指定したい場合はローカルの環境変数ENV['TZ']を『ENV['TZ'] = 'Asia/Tokyo'』のようにしてローカルタイムを一時的に書き換えてやる必要がある(一つの方法として)。日本を指定してもあまり意味はないが、特定の国を指定したいときもあるだろうから憶えておきたい。
  • 一方UTC(「世界標準時」)で表示したい場合はTimeではTime.now.utcのような形で引数で指定した協定世界時のTimeオブジェクトを取得することができる。
irb(main):001:0> Time.now.utc.strftime("%Y-%m-%d %H:%M")
=> "2016-12-14 02:34"
  • UNIXTIME(1414767600)の変換についてもTime.at(1414767600)の形でDATETIMEへの変換が可能unixtimeがミリ秒なのでtime + (usec/1000000) で値を変換しているはず。
irb(main):001:0> Time.at(1472607552).strftime("%Y-%m-%d %H:%M")
=> "2016-08-31 10:39"
  • 日付の加算減算はRubyだと通常active_supportを使って操作するのではないかと思うがDateTimeを使えば+1のような形で日付を加算できる。1/24加算すれば1時間進めることも可能。
irb(main):001:0>tomorrow = DateTime.now + 1
irb(main):002:0>tomorrow.strftime("%Y-%m-%d %H:%M")
=> "2016-12-15 12:41"

map join split をそれぞれ使わずに実装する

map,join,splitについてそれぞれ練習として使わないで実装してみる。
まずは配列の値を二倍にするだけのmap処理から

# 
ary1 = [1,2,3]
ary2 = ary1.map{|item|
  item * 2
}
p ary2

は下記。明示的に出力してやる必要がある。

ary1 = [1,2,3]
ary2 = Array.new
ary1.each {|item|
    ary2.push(item * 2)
  }
p ary2

下記はtab区切りテキストファイルにたいしてjoinを使わないで要素ごとに""でくくり”,”で区切った物

  line = ""
  meibo.split("\t").each {|field|
	line += "\"#{field}\"" + ","
  }
  line = line.chop
  ary1.push(line)

繰り返しで入れると要素末尾にまで,がついてしまうのでchopで末尾を削る必要があって入れているが、違和感の残る処理。

splitを使わずに書くパターン。基本は区切り文字の位置を検索⇛そこまでの値を取得して配列に格納、その後その位置までの文字列を削除して再度次の区切り文字を検索のループ

STDIN.each_line do |meibo|
  meibo.chomp!
  ary1 = []
  line = ""
  line = meibo.index(",")
  while line != nil do
	 ary1.push(meibo.slice(0..line-1))
     meibo.slice!(0..line)
	 line = meibo.index(",")
  end
  ary1.push(meibo)
  pp ary1
end

indexは検索対象を発見できないとnilを返すのでループ条件に指定可能。一回一回取得した文字列を削除せず、index("," line+1)で前回検索場所の次の位置から検索しても処理としては同じようにいけるか。

Ruby初学者のTIPS

Rubyを学び始めたので細かい学びの記録となります。

csvファイルの読み込み

csvファイルの読み込みについてライブラリのcsvが非常にわかりやすい。下記は名簿から年齢を抽出して平均を出す簡単な処理。

require "csv"

*scores = CSV.read('meibo.csv')
scores 

*ab = scores.transpose 

num  = ab[2].map(&:to_i)

puts num.inject{|sum, i| sum + i }/num.size

transposeは行と配列の入れ替え、injectは繰り返し計算用のメソッドでこちらはできることが多くちとわかりづらい(あとmapも)。map(&:to_i)の&の意味がさっぱりわからなかったがmapはブロックを引数にとるため&をつけることでブロックをオブジェクトとして扱っているような気がする。最初csvをreadするときにheaders: trueを入れていたところを一行目も読み込みたいのでfalseに変えても無反応だったので不思議だったがその場合はただ消すだけでいいらしい。まだ書き込み・出力の方は未着手なのでまた近日中に。