質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.50%

JSの冗長な処理を簡易にしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 260

kuroean

score 10

実現したいこと

対象の配列から
【A】idの配列
【B】ソートされたオブジェクトの配列
を取得したいです。

いちおう処理はできたのですが、いかんせん素人レベルのコピペだらけで、余計な処理があるように思います。

それが最後にあるソースコードですが、もっとスッキリさせた書き方にできないかと思っています。
もしアドバイスいただけましたら幸いです。

対象の配列

まずこれが対象の配列です。ここから【A】【B】を取得したいわけです。

const iniArray = [
  {id: '1', x_num: '100', y_num: null, z_num: null },
  {id: '2', x_num: null, y_num: '400', z_num: null },
  {id: '3', x_num: null, y_num: null, z_num: '300' },
  {id: '4', x_num: null, y_num: '200', z_num: null }
];

【A】 

対象の配列から extKeysの指定値 が null でないオブジェクトの id の配列を取得するのが【A】です。

たとえば extKeys = [ 'x_num', 'y_num' ] を指定した場合ならば、これらがnullである3を除外して、次の配列がほしいということです。

[ '1', '2', '4' ] 

【B】

対象の配列から extKeys が null でないオブジェクトを、「●_num」でソートして取得するのが【B】です。

先の【A】で取得したidを持つオブジェクトを「●_num」でソートし、次のオブジェクトの配列がほしいということです。

[
  {id: '1', x_num: '100', y_num: null, z_num: null },
  {id: '4', x_num: null, y_num: '200', z_num: null }, 
  {id: '2', x_num: null, y_num: '400', z_num: null }
];

素人ながら試したこと

以下があれこれ試行錯誤してできたコードになります。

1、2、3、4という処理ですが、ほしいのは【A】【B】の情報(下記なら1、3の情報)だけなので、もっとスッキリさせた書き方にできないかと思っています。

ご指導ご鞭撻のほど、よろしくお願い申し上げます。

/*
対象の配列
*/
const iniArray = [
  {id: '1', x_num: '100', y_num: null, z_num: null },
  {id: '2', x_num: null, y_num: '400', z_num: null },
  {id: '3', x_num: null, y_num: null, z_num: '300' },
  {id: '4', x_num: null, y_num: '200', z_num: null }
];

/*
1. extKeysがnullじゃなければidを検索
*/
function getExtIds( iniArray, extKeys ){
  let array = [];
  for (let i=0; i < iniArray.length; i++) {
    for (let j=0; j < extKeys.length; j++) {
      if( iniArray[i][extKeys[j]] !== null ){
        const id = iniArray[i]["id"];
        array.push(id);
      }
    }
  }
  // extKeysが [ 'x_num', 'y_num' ] なので、[ '1', '2', '4' ] が取得される
  console.log('---検索されたidの配列---');
  console.log(array);
  return array;
}

/*
2. 検索したidを持つオブジェクトを抽出する
*/
function getExtObj( iniArray, extIds ){
  let array = [];
  for (let i=0; i < iniArray.length; i++) {
    for (let j=0; j < extIds.length; j++) {
      if( iniArray[i]["id"] == extIds[j] ){
        const extObj = iniArray.find( e=>e.id && e.id === extIds[j] );
        array.push(extObj);
      }
    }
  }
  console.log('---抽出されたオブジェクト---');
  console.log(array);
  return array;
}

/*
3. 抽出されたオブジェクトを「●_num」で並び替える
*/
function getSortObj( extObj ) {
    return extObj.sort((a,b) => (a.x_num || a.y_num || a.z_num) - (b.x_num || b.y_num || b.z_num));
}

/*
4. 処理を実行
*/
const extKeys = [ 'x_num', 'y_num' ];
const extIds  = getExtIds( iniArray, extKeys );
const extObj  = getExtObj( iniArray, extIds );
const result  = getSortObj( extObj );
console.log('---「●_num」でソートされたオブジェクト---');
console.log( result );
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

まずA

const iniArray = [
  {id: '1', x_num: '100', y_num: null, z_num: null },
  {id: '2', x_num: null, y_num: '400', z_num: null },
  {id: '3', x_num: null, y_num: null, z_num: '300' },
  {id: '4', x_num: null, y_num: '200', z_num: null }
];
const extKeys = [ 'x_num', 'y_num' ]
const newArray=iniArray.filter(x=>!extKeys.map(y=>x[y]).every(z=>z==null)).map(x=>x.id);
console.log(newArray);

つづいてB

const newArray2=iniArray
.filter(x=>!extKeys.map(y=>x[y]).every(z=>z==null))
.map(x=>{
  x.sort=parseInt(x[Object.keys(x).filter(y=>y.match(/._num$/) && x[y]!=null)[0]]);
  return x;
}).sort((x,y)=>x.sort-y.sort).map(x=>{
  delete(x.sort);
  return x;
});
console.log(newArray2);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/08 18:21

    引き続きどうもありがとうございます。目玉が飛び出るくらいスッキリしましたね…!自分のコードと比べて思わず笑ってしまいましたw

    キャンセル

+1

extKeys が null でないオブジェクトだけピックアップした配列を作る」という関数を作っておけば、両方で使い回せます。

/*
対象の配列
*/
const iniArray = [
  {id: '1', x_num: '100', y_num: null, z_num: null },
  {id: '2', x_num: null, y_num: '400', z_num: null },
  {id: '3', x_num: null, y_num: null, z_num: '300' },
  {id: '4', x_num: null, y_num: '200', z_num: null }
];

// extkeysでのフィルタリング
function filtered(arr, extKeys) {
  return arr.filter(function(item){
    return extKeys.some(function(key){
      return item[key] !== null;
    });
  });
}

// idだけ抽出
function pickIds(arr, extKeys) {
  return filtered(arr, extKeys).map(function(item){
    return item.id;
  });
}



//並べ替えた配列
function sorted(arr, extKeys) {
  // 補助関数
  function pickValue(item) {
    for(var i = 0; i < extKeys.length; ++i) {
      var val = item[extKeys[i]];
      if(val) return val;
    }
  }

  // filteredで別な配列が生成するので、そのままsortに投げて問題なし
  return filtered(arr, extKeys).sort(function(a, b) {
    const aValue = pickValue(a);
    const bValue = pickValue(b);
    if(aValue < bValue) return -1;
    if(aValue > bValue) return 1;
    return 0;
  });
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/08 18:26

    そのご発想ステキです。かなり使えそうです。どうもありがとうございます。わたしは質問のコードを書くのに2日かけたのですが(笑)、みなさん10分やそこらで出来ちゃうんですね…。

    キャンセル

  • 2019/08/08 22:57

    Array.prototypeには色々メソッドがありますので、これらをどれだけ使いこなせるかが配列処理の肝になってきます。
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Methods

    キャンセル

  • 2019/08/09 01:26

    とても便利なものがたくさんありますね。これは知っておいてよかったです。情報感謝申し上げます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる