- ベストアンサー
上手な配列への代入方法
Data = new Array(); var Name = [ Data[0] = [0,0,0,0,0,0]; [0,"なし"], [0,"--果物--"], Data[1003] = [0,0,0,0,0,0]; [1003,"りんご"], Data[1001] = [0,0,0,0,0,0]; [1001,"みかん"], [0,"--野菜--"], Data[203] = [10,10,0,2,0,5]; [203,"レタス"], Data[202] = [10,10,0,2,0,5]; [202,"キャベツ"], [0,"--肉--"], Data[100] = [5,5,0,0,0,0]; [100,"鶏肉"], Data[105] = [5,5,0,0,0,5]; [105,"牛肉"], [0,"--その他--"], Data[211] = [10,10,0,2,0,5]; [211,"チーズ"], Data[200] = [10,10,0,2,0,5]; [200,"バター"], ~~ var Html = "<SELECT onchange=calc(this.value)>"; for(i=0;i<Name.length;i++){ Html += "<OPTION value="+ Name[i][0] +">"+ Name[i][1] +"</OPTION>"; } Html += "</SELECT>"; selectに表示される順番を簡単に入れ替えるために右のNameを入力したいんですが 何かいい方法はないでしょうか? 単にName代入部分をほかの場所に書けばいいのですが、 結構頻繁に項目追加、順番入れ替えをするので、人間的に読みやすさを考えて出来ればデータと同じ行に書きたいのです(出来ればDataにくっつけたいところですが) 制限としてCookieでData[x]のxを記憶しているため、ここがずれると困ります ※動かない理由はわかっています、大体やりたいことを表現してみました
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
> 出来れば配列番号を明記しないで 質問の内容と矛盾しているわよ。 > 制限としてCookieでData[x]のxを記憶しているため、ここがずれると困ります それともxはなくてもいいってこと? まあそれはともかく > Indexのそれ以下を1ずつずらさないといけなくなります 引数にせずにグローバル変数で管理して index++していけばいいじゃない。
その他の回答 (5)
- fujillin
- ベストアンサー率61% (1594/2576)
No2、No5です。 こんにちは。 >valueの値をcookieで保存しているのでたとえば ・・・・・ >のように入れ替えた場合、<OPTION value=' + i +'>に対するデータが >変わってきませんか? はい、その通りです。 全体像が不明なので、質問で明示されている範囲から考えるとその方が簡単だろうと思った次第です。 (「このコードを他に用いていない場合は」とお断りしてありますよね?) 順番が入れ替わるのが前提であれば、cookieなどに保存しておくのは、当然、照合用のコードでないとまずいですね。 例で言えば、iではなくName[i][0]を保存しておくことになります。 cookieとの照合がどのくらい頻繁にあるのか不明ですが、多分、最初に照合しておけば良いのでしょうから、1度だけFor~で照合してインデックスを読替えておけば、処理自体はテンポラリな引数(i)を使用していても問題はないと想像します。 もちろん、もともとご提示のように、全体を「照合用のコード」を用いて処理するという方法でもよいはずです。 どのような方法にするのが便利そうかは、全体の処理の内容から決めればよいのではないでしょうか? そもそもは、『配列の代入部分をわかりやすく記すには、どのような構成にすればよいか』という観点からスタートしていますので、他の(質問文に現れていない)部分までには配慮はしていません。 ついでに、今、見ていて気がつきましたがグループラベルの判定は if ((''+Name[i][0]).substr(0,2)=='--') よりも if (Name[i].length=1) のほうが簡単そう。 あるいは、ラベルの項目を配列でなくしておけば if (Name[i].length) でも判定できそうな気がします。(←未確認)
- fujillin
- ベストアンサー率61% (1594/2576)
No2です。 >連想配列?のことですか? はい、そうです。 多分、1003とかは数字というよりも識別コードなんだと想像したのですが、Data[1003]とかやるとData[0]~Data[1003]までの配列が出来るわけで、それが全部埋まっているとは思えなかったので… >計算のときvalueで呼び出す配列番号を指定する良い方法が思い >つかず断念してました 識別コードをキーにして、全部を連想配列に入れてしまえばよいのではと思いましたが、実験したところ、ブラウザによって取り出すときにキーでソートしてしまうものがあるみたいなので、インデックスだけ別に連想配列で作成しておいたほうがよさそうですね。 ついでに、(想像ですが・・)「--果物--」などは選択用のアイテムではなくて、グループ化したラベルだと解釈すれば… 定義は var idx={}; //インデックス用のハッシュ var Name = [ [0,'なし',0,0,0,0,0,0], ['--果物--'], [1003,'りんご',0,0,0,0,0,0], [1001,'みかん',0,0,0,0,0,0], ['--野菜--'], [203,'レタス',10,10,0,2,0,5], [202,'キャベツ',10,10,0,2,0,5], ['--肉--'], [100,'鶏肉',5,5,0,0,0,0] ・・・・・ などとしておいて、 セレクトボタンのソース作成時に var gr=false; var Html = "<SELECT onchange=calc(this.value)>"; for(var i=0; i<Name.length; i++){ if ((''+Name[i][0]).substr(0,2)=='--') { Html +=(gr?'</optgroup>':'')+'<optgroup label="'+ Name[i][0] + '">'; gr=true; } else { Html +='<OPTION value=' + Name[i][0] +'>' + Name[i][1] + '</OPTION>'; idx[Name[i][0]]=i; }} Html +=(gr?'</optgroup>':'') + '</SELECT>'; みたいにすれば、Name[]の引数をind[value]にすることでOKでは? (実際の使用法がよくわかってないけど、想像通りなら、最初の[0,'なし'…]も不要になると思うけど、とりあえずそのまま。) *)とりあえず原案を尊重して、識別用のコード(1003など)を使用して対象させていますが、このコードを他に用いていない場合は、オプションのバリューにiの値をそのまま設定しておけば、idxなんていう中間のインデックスも不要になるし、もっと簡単にできます。 Html +='<OPTION value=' + i +'>' + Name[i][1] + '</OPTION>'; でよくなるし、idxも不要でoptionのvalueをそのままインデックスに使えばよいことになります。
補足
なるほど、option部品を作成するときにIndex番号を入力すれば良いわけですね 盲点でした >ついでに、(想像ですが・・)「--果物--」などは選択用のアイテムではなくて、グループ化したラベルだと解釈すれば… <optgroup>というタグもあったんですね グループとして設定されているからなのか、オンマウスしてもフォーカスが行かないのはちょっと便利なんですが 勝手に子のoptionがインデントされてしまうのが逆に邪魔なので(スタイルで何とかなりそうな気はしますが) まだ作ってないのですが、Select部品作成時に valueが0の場合 Optionにstyle=color:#0000ff; font-weight:bold; などとやろうかなと考えています >*)とりあえず原案を尊重して、識別用のコード(1003など)を使用して対象させていますが、このコードを他に用いていない場合は、オプションのバリューにiの値をそのまま設定しておけば、idxなんていう中間のインデックスも不要になるし、もっと簡単にできます。 自分が理解してないだけかもしれませんが valueの値をcookieで保存しているのでたとえば [0,'なし',0,0,0,0,0,0], ['--果物--'], [1001,'みかん',0,0,0,0,0,0], [1003,'りんご',0,0,0,0,0,0], のように入れ替えた場合、<OPTION value=' + i +'>に対するデータが変わってきませんか?
問題ありそう~!^^; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <title>サンプル</title> <body> <form action="" method=""> <p> <select id="p" onChange="calc(this.value)"> </select> </p> </form> <script type="text/javascript"> var data = { 0: [0,0,0,0,0,0,"なし"], 999: [0,0,0,0,0,0,"--果物--"], 1003: [0,0,0,0,0,0,"りんご"], 1001: [0,0,0,0,0,0,"みかん"], 199: [0,0,0,0,0,0,"--野菜--"], 203: [10,10,0,2,0,5,"レタス"], 202: [10,10,0,2,0,5,"キャベツ"], 99: [0,0,0,0,0,0,"--肉--"], 100: [5,5,0,0,0,0,"鶏肉"], 105: [5,5,0,0,0,5,"牛肉"], 198: [0,0,0,0,0,0,"--その他--"], 211: [10,10,0,2,0,5,"チーズ"], 200: [10,10,0,2,0,5,"バター"] }; window.onload = function () { rebuild('p', data, getCookie('x')); } function rebuild (elementId, data, sno) { var e = document.getElementById(elementId); var o, key, str; var reg0 = /^--.+--$/; var gp = null; var tmp; // while (o = e.firstyChild) e.removeChild(o); for (key in data) { str = data[key][6]; if (str && str.match(reg0)) { gp = document.createElement('optgroup'); gp.setAttribute('label', str); gp = e.appendChild(gp); } else { tmp = gp ? gp: e; var op = document.createElement('option'); op.value = key; op.selected = key == sno; op.appendChild(document.createTextNode(str)); tmp.appendChild(op); } } } function calc(val) { setCookie('x', val, 100); alert("0="+data[val][0]+', 6='+data[val][6]); } function getCookie( name ) { name = encodeURIComponent( name ).replace( /([.*()])/g, '\\$1' ); var value = document.cookie.match( RegExp ( name + '\\s*=\\s*(.*?)(?:[\\s;,]|$)' ) ); return value ? decodeURIComponent( value[1] ) : ''; } function setCookie ( name, value, day, path, domain ) { return document.cookie = encodeURIComponent( name ) + '=' + encodeURIComponent( value ) + '; ' + 'expires=' + new Date( (new Date) - 86400000 * -day ).toUTCString() + '; ' + ( path ? 'path=' + encodeURI( path ) + '; ': '' ) + ( domain ? 'domain=' + encodeURI ( domain ) + '; ': ''); } </script>
補足
for (key in data)でループさせると入力した順に回るんですね 知りませんでした ですが下の方のようにブラウザによってはやろうとしていることが出来ないようなのでちょっと問題かもです
- fujillin
- ベストアンサー率61% (1594/2576)
なんだかよくわからないけど、想像で… >Data[x]のxを記憶しているため、ここがずれると困ります xは識別子で使っているのでしょうから、定義を誤記しない限りは順番等をいくら変えても変わらないように見えるけど? あと、いきなりData[1003]とかになってるけど、連番の配列に入れるべき内容なのでしょうか?(ハッシュとかが合っているのでは?) 質問文では、イメージで書かれているみたいなので、Nameの内容がどこまでなのか良くわからないですが、想像で書くと、わかりやすく記載したいのなら、全部をセットで定義すればよいのでは? たとえば、 var Name = [ [0,'なし','0,0,0,0,0,0'], [0,'--果物--'], [1003,'りんご','0,0,0,0,0,0'], [1001,'みかん','0,0,0,0,0,0'], [0,'--野菜--'], [203,'レタス','10,10,0,2,0,5'], [202,'キャベツ','10,10,0,2,0,5'], [0,'--肉--'], [100,'鶏肉','5,5,0,0,0,0'], ・・・・・・・・・・ ご質問文の通りに配列にデータを入れたいのなら、 Data=[]; for (var i=0; i<Name.length; i++)if (Name[i][2]) Data[Name[i][0]]=Name[i][2].split(','); とでもしておけば良いですけれど、多分、事前にDataにセットしておく必要はないのではないでしょうか。 処理内容が不明なのでまったくの想像ですが、都度、参照する程度で済む処理なのではなかろうかと想像します。そうすればDataの配列そのものが不要になりますね。
補足
>xは識別子で使っているのでしょうから、定義を誤記しない限りは順番等をいくら変えても変わらないように見えるけど? 「xの数値が」かわると困ると言うことです 行はずれても問題ないです >あと、いきなりData[1003]とかになってるけど、連番の配列に入れるべき内容なのでしょうか?(ハッシュとかが合っているのでは?) HTMLへの出力順番を行ごと変えたために1003番が一番上に来ただけです ハッシュとは何でしょう 連想配列?のことですか? >参照する程度で済む処理 fanction calc(value){ var DataHTML = ""; DataHTML += "種類 :"+ Data[value][0]+"<BR>"; DataHTML += "カロリー :"+ Data[value][1]+"<BR>"; ~~ などと表示をしているだけです ごくまれに書き換えることはありますがほぼ参照だけです 書いていただいたName配列の方法は考えたのですが 計算のときvalueで呼び出す配列番号を指定する良い方法が思いつかず断念してました 思いついたのは for(i=0;i<Name.length;i++){ if(value==Name[i][0]) value=i; } と呼び出されるたびに毎回ループ処理をやるくらいでしょうか
- askaaska
- ベストアンサー率35% (1455/4149)
読みにくいわ。 そしてやりたいことがわからない。 正しいコードが書かれていれば 判断の仕様があるんだけど。 というツッコミをしたいんだけどダメかしら。 コードは文法に従って書いてあれば それを理解する人にはそれが一番読みやすいものよ。 Nameはたぶん<option>のvalue属性と表示項目に対応しているのよね。 そして<select>で選択されたvalue値に対応する Data[value]を取り扱うてことなのかしら。 私ならいっそ <option value="0,0,0,0,0,0">りんご</option> とかやっちゃうけどね。 そうすればそれぞれ1行になるわ。 そういうことじゃないのかしら? もうNameとDataの両配列が取り外せない前提で 且つ、どうしてもならべて値をセットしたいというなら そういう関数を作ればいいのよ。 function setDataName(index,id,value,data) { Data[id]=data; Name[index]=[id,value]; } こんな感じ。
補足
正しいコードと言われても、動くコードとしては var Name = [ [0,"なし"], [0,"--果物--"], [1003,"りんご"], [1001,"みかん"], [0,"--野菜--"], [203,"レタス"], [202,"キャベツ"], [0,"--肉--"], [100,"鶏肉"], [105,"牛肉"], [0,"--その他--"], [211,"チーズ"], [200,"バター"], ~~ の部分がほかの場所に書かれていて、Data部分の右にはコメントで何のデータかわかるように「//りんご」などとかかれてます calcの部分はただ計算しているだけなので省いていたんですがここのことでしょうか >Nameはたぶん<option>のvalue属性と表示項目に対応しているのよね。 >そして<select>で選択されたvalue値に対応する >Data[value]を取り扱うてことなのかしら。 そのとおりです やりたいことと言うと、 左のData部分とそれに対応した右のName部分があり (大量にあるので)HTMLに出力する時に左のData部分ごと行を入れ替え・削除・追加するだけで出力順番を変えれるようにしたいのです ><option value="0,0,0,0,0,0">りんご</option> これがやりたいことに近そう何ですが活用方法がよくわかりません >function setDataName(index,id,value,data) { >Data[id]=data; >Name[index]=[id,value]; >} これを作ったうえで setDataName(0,0,"なし",[0,0,0,0,0,0]); setDataName(1,0,"--野菜--",[0,0,0,0,0,0]); setDataName(2,203,"レタス",[10,10,0,2,0,5]); setDataName(3,202,"キャベツ",[10,10,0,2,0,5]); のようにやれば出来なくはないみたいですが、 レタスとキャベツの間に項目を追加したくなったとき、Indexのそれ以下を1ずつずらさないといけなくなります 出来れば配列番号を明記しないで追加していくような感じで増やしていきたいです かなりわかりづらいかもしれません、すみません
補足
>function setDataName(index,id,value,data) { >Data[id]=data; >Name[index]=[id,value]; >} >それともxはなくてもいいってこと? idはずれると困りIndexは上の行から順に、と言う感じです >引数にせずにグローバル変数で管理して >index++していけばいいじゃない。 これでいけそうです