Search code examples
javascriptarraystypescriptecmascript-6ecmascript-5

How to get a value that never appear into specific property from the Array of objects


I have an array that contains a list of objects with two properties source and target. I want to find a value that never appears into target.

Currently, I came up with a very weird solution. According to the provided code, I am creating two separate arrays by iterating through an a array. all with all elements and targets with only target elements. Then I apply a filter on it and it returns the answer.

    const a = [
      { source: '2', target: '3' },
      { source: '1', target: '2' },
      { source: '3', target: '4' },
      { source: '4', target: '5' }
    ];

    const all = ['1', '2', '3', '4', '5'];
    const targets = ['3', '2', '4', '5'];
    console.log(all.filter(e => !targets.includes(e))[0]);

Do we have some efficient solution, which not demands to create these two arrays and I know return element would be only one. So I don't want to get an array as an answer


Solution

  • You can use .find to find the first matching element:

    const a = [
      { source: '2', target: '3' },
      { source: '1', target: '2' },
      { source: '3', target: '4' },
      { source: '4', target: '5' }
    ];
    const sources = [];
    const targets = [];
    a.forEach(({ source, target }) => {
      sources.push(source);
      targets.push(target);
    });
    
    console.log(sources.find(e => !targets.includes(e)));

    If you want better performance, use a Set instead of an array for the targets, so you can use .has instead of .includes (resulting in overall complexity of O(n) rather than O(n^2)):

    const a = [
      { source: '2', target: '3' },
      { source: '1', target: '2' },
      { source: '3', target: '4' },
      { source: '4', target: '5' }
    ];
    const sources = [];
    const targets = new Set();
    a.forEach(({ source, target }) => {
      sources.push(source);
      targets.add(target);
    });
    
    console.log(sources.find(e => !targets.has(e)));