Observable查找嵌套属性

时间:2018-05-25 21:29:57

标签: angular rxjs observable

Observable返回此对象

[
  {
    "args": { },
    "output": [
      {
        "id": "1",
        "name": "Jack",
        "lastName": "Sparrow",
      },
      {
        "id": "2",
        "name": "Davy ",
        "lastName": "Jones",
      }
    ],
  }
]

是否有办法使用RxJx运算符返回output数组id===2的元素?所以只得到这个:

{
  "id": "2",
  "name": "Davy ",
  "lastName": "Jones",
}

我认为我应该使用find,但无法找到嵌套对象的使用示例。

我当前的代码(我知道find部分不正确):

  public getUserData(id: number) {
    this.http.get<any>(URL)
      .pipe(
         find(element => element.output)
      )
      .subscribe(res => {
       console.log(res)
     })
  }

4 个答案:

答案 0 :(得分:3)

只需使用mergeMap(在其他 Rx 实施中通常称为flatMap)和filter的组合!

mergeMap允许您:

  1. 每个项目映射到列表(即,为每个事件发出值列表)
  2. 压扁列表一起返回一个事件流
  3. ...然后你filter只保留与你选择的谓词相匹配的人(在你的情况下:output => output.id === 2)。

    您可以使用下面的代码段,您可以自己编辑收到的响应,然后点击相应的按钮来触发事件。

    &#13;
    &#13;
    const data = [{
      "args": {},
      "output": [{
          "id": "1",
          "name": "Jack",
          "lastName": "Sparrow",
        },
        {
          "id": "2",
          "name": "Davy ",
          "lastName": "Jones",
        }
      ],
    }];
    
    const textarea = document.querySelector('#data-source');
    const button = document.querySelector('#trigger-response');
    
    // Assume `myObservable comes from the result of an Ajax request`
    const myObservable = rxjs
      .fromEvent(button, 'click')
      .pipe(rxjs.operators.map(() => JSON.parse(textarea.value.replace(/,(?=\s*\})/mg, ''))));
    
    myObservable.pipe(
      rxjs.operators.mergeMap(response => response[0].output),
      rxjs.operators.filter(output => output.id === '2')
    ).subscribe(x => console.log(x));
    &#13;
    body {
      display: flex;
      align-items: center;
    }
    
    textarea {
      flex-grow: 1;
    }
    &#13;
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.2.0/rxjs.umd.min.js"></script>
    <textarea id="data-source" rows="20">[
      {
        "args": { },
        "output": [
          {
            "id": "1",
            "name": "Jack",
            "lastName": "Sparrow",
          },
          {
            "id": "2",
            "name": "Davy ",
            "lastName": "Jones",
          }
        ],
      }
    ]</textarea>
    <button id="trigger-response">Click Me</button>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:1)

我是这样的:

this.http.get<any>(URL)
    .pipe(
        mergeAll(), // flatten the root array
        mergeMap(item => item.output), // flatten the output array
        filter(output => output.id === '2')
    )
    .subscribe(res => {
        console.log(res); // Tahdah!!
    })

答案 2 :(得分:0)

如果您不关心可观察物的发射(例如它们的发射频率),您可以使用native Javascript Array Prototype中的filter {来自Observables的{3}}。从根本上说它们是不同的,但除非你有任何强有力的理由使用Observable,你可以使用数组。代码更短,性能更高:

public getUserData(id: number) {
    this.http.get<any>(URL)
        .map(data => data.output.filter(x => x.id === '2'))
}

事实上,对于您的情况,如果您 SURE id进行过滤(假设是唯一的),则可以es6使用public getUserData(id: number) { this.http.get<any>(URL) .map(data => data.output.find(x => x.id === '2')) } } 句法。它将返回满足条件的第一个元素:

$( "body" ).on( "keyup", ".attribuzioneabbonamento", function(){
    var AbbonamentoCodice = $(this).val();
    var IdRiga = $(this).attr('dd');

        if(AbbonamentoCodice.length == 13){

                $.post("engine.php",
                {
                    Action: 'attribuisciabbonamento',
                    Code: AbbonamentoCodice,
                    IdRiga: IdRiga
                },

                function(data, status){
                    if(status == 'success'){
                        $('.abbonamentorisposta'+IdRiga).html(data);

                    }else{

                    }

              });


        }
}); 

答案 3 :(得分:-1)

您可以使用过滤器:

        //Function to get random number
    private static readonly Random getrandom = new Random();

    public static int GenRan(int min, int max)
    {
        lock (getrandom) // synchronize
        {
            return getrandom.Next(min, max);
        }
    }

    private void selButt_Click(object sender, EventArgs e)
    {
        int iLvl = 0;
        int preRoll = 0;
        iLvl = int.Parse(itemLvl.Text);
        if (ringType.SelectedIndex == 0)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Steel_Ring.png");
            Random obj = new Random();
            if ( iLvl >= 1 || iLvl <= 4)       // teir 8
            {
                preRoll = obj.Next(5, 9);
            }
            else if (iLvl >= 5 || iLvl <= 10)  // teir 7
            {
                preRoll = obj.Next(10, 19);
            }
            else if (iLvl >= 11 || iLvl <= 17)  // teir 6
            {
                preRoll = obj.Next(20, 29);
            }
            else if (iLvl >= 18 || iLvl <= 23)  // teir 5
            {
                preRoll = obj.Next(30, 39);
            }
            else if (iLvl >= 24 || iLvl <= 29)  // teir 4
            {
                preRoll = obj.Next(40, 49);
            }
            else if (iLvl >= 30 || iLvl <= 35)  // teir 3
            {
                preRoll = obj.Next(50, 59);
            }
            else if (iLvl >= 36 || iLvl <= 43)  // teir 2
            {
                preRoll = obj.Next(60, 69);
            }
            else if (iLvl >= 44 || iLvl <= 100)  // teir 1
            {
                preRoll = obj.Next(70, 79);
            }
            else
            {
                MessageBox.Show("Item Level incorrect! ");
            }
            prefixBox.Text = preRoll.ToString();
        }
        else if (ringType.SelectedIndex == 1)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Opal_Ring.png");
        }
        else if (ringType.SelectedIndex == 2)
        {
            ringpic.Load("E:\\ProgProj\\POERingMaker  Alpha 1.0\\POERingMaker  Alpha 1.0\\Resources\\Prismatic_Ring.png");
        }
    }