ラベル programming の投稿を表示しています。 すべての投稿を表示
ラベル programming の投稿を表示しています。 すべての投稿を表示

2012年9月4日火曜日

JavaScriptのslice()とsubstring()とsubstr()

JavaScriptには、部分文字列を取得するメソッドが3つある。slice()とsubstring()とsubstr()である。
なんで似ているメソッドが3つもあるのか不明だけど、整理する意味でちゃんと書いておく。

  • String.prototype.slice (start, end)
引数startから引数endまでの部分文字列を新しい文字列値で返す。
endは省略でき、その場合は末尾を指定したのと同様になる。
負数の場合は末尾からのインデックス値となる。
'0123456789'.slice(2, 8);       // 234567
'0123456789'.slice(2);          // 23456789
'0123456789'.slice(-5, -2);     // 567
  • String.prototype.substring (start, end)
引数startから引数endまでの部分文字列を新しい文字列値で返す。
endは省略できない。
負数の場合は0に置き換わる。
'0123456789'.substring(2, 8);       // 234567
'0123456789'.substring(-5, 2);      // 01
  • String.prototype.substr (start, length)
引数startからlength数の新しい文字列値を返す。
lengthは省略でき、その場合は元の文字列の末尾まで指定したのと同様になる。
startが負数の場合は0に置き換わる。lengthが負数の場合は・・・不明?
'0123456789'.substr(2, 8);       // 23456789
'0123456789'.substr(2);          // 23456789
'0123456789'.substr(-5, 2);      // 56

これら3メソッドはJavaScriptの仕様であるECMA262にちゃんと載っている。
  • 15.5.4.13 String.prototype.slice (start, end)
  • 15.5.4.15 String.prototype.substring (start, end)
  • B.2.3 String.prototype.substr (start, length)
substr()だけ付録のページに載っているのだが、サブ的な扱いなのかしら?

2012年8月2日木曜日

JavaScriptである値がパターンにマッチしたらtrueを返す処理

単純に、RegExpオブジェクトのtest()を使えばよい。
var value = "abcdef";
var result = (/abc/).test(value); // true
以下でもOK。こっちはStringオブジェクトのmatch()を使っている。
var value = "abcdef";
var result = !!value.match(/abc/); // true
match()はマッチした結果を配列で返し、全くマッチしない場合はnullを返す。なので、単にマッチしたかどうかの結果だけを知りたい場合は、!演算子を2回使えばよい。

  • value.match(/abc/) → abc
  • !value.match(/abc/) → !abc → false
  • !!value.match(/abc/) → !!abc → !false → true

上記の!abcがfalseになるのは、abcが型変換でブーリアン型(true)になるからである。
型変換でfalseになる値は以下の通りで、それ以外はtrueである。

  • 数値0
  • 数値NaN
  • null値
  • undefined値
  • 空文字

JavaScriptのとあるソースを呼んでて、!!value.match(/abc/)なるものがあって、何やってるのかよく分からなかったからメモを残しました。単純にRegExpのtest()を使うのとどっちがいいですかね?

2012年7月25日水曜日

jQueryのバージョンをコードで確認する方法

jQueryのバージョンをコードで確認する方法は簡単。
jQueryオブジェクトにはjQueryプロパティというバージョンを格納しているプロパティがあるので
それを参照すればおk

alert($().jquery); // 例えば、1.7.2と表示される

検索で「jQueryプロパティ」と入れても「jQueryのプロパティ」と解釈されてなかなか出てこないんだな...

2012年6月28日木曜日

JavaScriptのsetTimeout()で指定する関数の引数に値を渡したいとき

JavaScriptで定期的に処理を行わせたいときに、setTimeout()またはsetInterval()を使う事があります。
// 1秒間隔でdoSomething()を実行
setInterval(doSomething, 1000);
その第1引数には処理を定義した関数を与えるのですが、その関数の引数に値を渡したい時は以下のように呼びます。
setInterval(doSomething, 1000, value);
setInterval(doSomething, 1000, value1, value2, value3);
あるいは
setInterval("doSomething('" + value + "')", 1000);
文字列で渡すパターンは途中にシングルクォートを入れるのがミソらしいんだが、具体的な理由は不明(´・ω・`)
ちなみに、MOZILLA DEVELOPER NETWORKのwindow.setTimeoutwindow.setIntervalに関数の説明が書いてあります。ECMA262には書いていませんでした。ということは、ECMAで定めた関数じゃないんですかね。

その他参考サイト:
setTimeoutで引数が入った関数を呼ぶ

JavaScriptで小数の表示

暇つぶしにJavaScriptでストップウォッチを作っていたのだが、0.1秒とか11.5秒とかはそのまま表示されるのに、10.0秒みたく小数点以下が全部0だと、それらが切り捨てられて10と表示されてしまう。10.0と表示したい時は以下のメソッドを使えばおk

var val = 10;
val.toFixed(1);  // 10.0

toFixed()は小数点表示の文字列値に変換するメソッドです。引数は、小数点以下の桁数を表します。

ちなみに、JavaScriptの数値型(Numberオブジェクト)は64ビット浮動小数点数です。なので数値計算は(たとえ整数のつもりでも)内部では全て実数として扱われます。小数点以下が全て0のときに文字列にすると小数点以下が切り捨てられて、整数に見えるとのこと。ちなみに、ビット演算の時は内部では32ビット整数で計算されるみたい。

参考サイト:
javascript - には整数はない

2012年6月23日土曜日

JavaScriptのArgumentsオブジェクトを配列に変換

JavaScriptには、関数の引数情報を表すArugmentsオブジェクト、DOM APIのgetElementsByTagName()が返すNodeListオブジェクトのように、配列だけど配列でないオブジェクト(以下、配列風オブジェクトと呼ぶ)が存在する。

配列ではないので、単純に配列(Arrayオブジェクト)のメソッドをそのまま呼ぶ事はできない。call()やapply()を用いて呼べばOKなメソッドもあるが、場合によっては配列に変換しないとダメとか、むしろ変換しちゃったほうが何かと都合がいいとかあるだろう。

変換方法は以下のコードを1行実行するだけで良い。
var array = Array.prototype.slice.apply(arguments);

Arrayオブジェクトのslice(start, end)は、配列から指定したインデックスの要素を抜き出した新しい配列を返す(インデックスを指定しなかったら中身が全く同じの新しい配列を返す)メソッドで、このメソッドを使う事で配列風オブジェクトから配列が返ってくる。

そもそも、なんでこいつを使うと本物の配列が返るのかというと、配列風オブジェクトの特徴が

  • lengthを持つ
  • 数値プロパティを持つ(プロパティ名が数値なので、arguments[1]とやると値を取得できる)

であり、slice()が以下のような実装になっているからだと思う。
var slice = function(start, end) {
 var newArr = [];
 var i = start || 0;
 end = end || this.length;

 for (; i < end; i++) {
  newArr.push(this[i]);
 }

 return newArr;
}

↑だいぶざっくりと書いているので気をつけてください(startの値が負数だとか、endの値が配列の長さ以上だとか考慮してないっす)。メソッドになっていないのも勘弁してください。
ポイントはthis(apply(), call()で呼べばthisは配列風オブジェクト)とpush()のところで数値でプロパティ値を取得してるところかな。

2011年7月16日土曜日

相対パスだったら絶対パスに直す

そのやり方について。

文字列が絶対パスかどうか判定して、もし相対パスだったらgetCanonicalPath()で絶対パス取得する。


File file = new File(str); // パスを引数に入れてFileインスタンス生成
if (!file.isAbsolute()) {  // 絶対パスの判定にisAbsolute()を使う
    try {
        str = file.getCanonicalPath(); // getCanonicalPath()で絶対パスを取得する
    } catch (IOException e) {  // getCanonicalPath()は例外をthrowするのでcatchする
        e.printStackTrace();
    }
}

基本だけど、ちゃんと記録しておこうと思って書きました。

2010年4月30日金曜日

C#始めました

研究室の勉強会を通じてC#を勉強することにしました。1ヶ月前に勉強会が始まりましたが、本格的にC#でコーディングしたのは今日が初めて。


とりあえず、今までやってきたJavaやActionScriptなどとの違いを分かった分だけ列挙すると



  • コンソール出力はConsole.WriteLine();
  • しかも、第1引数の文字列中に"{0}"と書いておくと、第2引数の値がバインドされる(printfと同様の使い方ができる。)"{1}"と書けば、第3引数の値がバインド
  • メソッド名はアッパーキャメルで定義。プロパティもアッパーキャメル
  • インターフェース名は一番先頭にIをつける。
  • 静的クラスとは、静的メンバ、静的メソッドのみを定義したクラスのこと
  • 特に、class宣言のときにstaticキーワードをつけるとインスタンス化を防げる(privateであるデフォルトコンストラクタを用意しなくてよい)
  • 静的コンストラクタとは、静的メンバ、静的メソッドやそのコンストラクタのあるクラスが初めてインスタンス化されるとき「のみ」に実行されるコンストラクタ。静的な値の初期化を行いたいときに利用。コンストラクタ宣言の前にstaticをつける。Javaで言うところのstaticイニシャライザと同じ使い方


というくらいだろうか

C#を勉強しつつ、Silverlightもマスターしてしまおう(`・ω・´)

2009年4月12日日曜日

[programming]配列の要素を回転させるプログラム


最近は友達から借りたプログラミングの本を読んで時間を潰すことが多い.どれも難しい問題ばっかりで理解するのに苦労する.今日はその中から1つ問題をチョイス.

「要素がn個の配列をi要素分だけ回転させる(後ろに持っていく)プログラムを書きなさい」っていう問題がある.ようは,

1,2,3,4,5,6,7,8,9,10

と入ってる配列を「3回転させてね♪」と指定したら,

4,5,6,7,8,9,10,1,2,3

とすればいいので,例えば以下みたいなプログラムのように,1回ずつ移動させる関数を定義し,その関数を3回呼び出せば実現できる.
・・・
int a[n]; //要素n個で配列を定義
・・・
int func(){
int tmp = a[i];
int i;
for(i=0; i< n; i++){
if(i==n-1) a[i] = tmp;
else a[i] = a[i+1];
}
}

しかし,問題には条件があって,「メモリを数十バイトしか使わずに実行時間もnに比例するだけ」のプログラムにしないといけない.このプログラムだとnに比例しないのでダメなのである(´・ω・`) 配列を複数個用意するなんてもっての外である.



じゃあ実際にどうやってそれを実現するのかというと,本に書いてあるヒントでは,a[0]を1時保管用のtに入れておき,その後はa[0]にa[i]を入れる.次はa[i]にa[2i]を,a[2i]にa[3i]・・・てな感じで移していく.つまり,3つ移すのなら3つ置きにずらしていけばいいということですな,なるほどぅ

で,書いたのがこれ

for(m=0; m< gcd(n, i); m++){
//最大公約数に達するまでm番めのグループを移動する
tmp = a[m]; //一時保管庫へ
j = m; //転送先を初期化
while(1){
k = j; //転送先をセット
j = j + i; //転送元をセット
if(j< n){
a[k] = a[j]; //移す
}else{ //転送元添字がn以上だったら
j = j%n;
if(j==m){ //転送元添字がmと同じなら
a[k] = tmp; //一時保管用のを移す
break;
}
a[k] = a[j];
}
}


なんか,もうちょっとまとまって書けないのかねぇ(´・ω・`)
本のヒントの通りに書いたわけだが,for文で最大公約数に着目してループしている.ここがどうしても理解できないorz 確かに移動できてるんだけどねぇ