1

The following returns all arrProps that have a matching arrValues value:

const arr = [
{ arrProps: [{name: '1', prop2: 'aaa'}], arrValues: ['apple', 'orange'] },
{ arrProps: [{name: '2', prop2: 'bbb'}], arrValues: ['taco', 'orange' ] },
{ arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: ['fish', 'apple', 'orange'] }
];

const result = arr
  .flatMap(({ arrValues }) => arrValues )  // all values
  .filter((value, index, coll) => coll.indexOf(value) === index) //unique values
  .reduce((acc, value) => {
      const parentProp = arr      // name, prop2, arrValues
          .filter((obj) => obj.arrValues.includes(value))
          .map((obj) => obj.arrProps[0].name);
          //.map((obj) => [{ source: obj.arrProps[0].name, value: obj.arrValues[0], sourceID: null}]);

      acc[value] = (acc[value] ? [...acc[value], parentProp] : [parentProp])
      .join(',');
      acc[value] = parentProp
      
    return acc;
}, {})

console.log(result);
console.table(result);

enter image description here

I need to add additional properties to arrValues, thereby using objects rather than values:

const arr = [
    { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ symbol: 'apple', id: '1.apple' }, {symbol: 'orange', id: '1.orange'}] },
    { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ symbol: 'fish', id: '2.fish' }, { symbol: 'pizza', id: '2.pizza' }, { symbol: 'red', id: '2.red' }] },
    { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ symbol: 'grape', id: '3.grape'}, { symbol: 'apple', id: '3.apple' }] },
];

From simply 'apple', I need to add some additional uniquely identifying values, i.e. { symbol: 'apple', id: '1.apple' }

I'm sure it's in here:

aMap.filter((value, index, coll) => coll.indexOf(value) === index) // <--- filter issue

Which is returning the object (previous data model, just the value 'apple', 'orange'...):

Array(7) [Object, Object, Object, Object, Object, Object, Object]
    [[Prototype]]: Array(0)
    length: 7
    0: Object {symbol: "apple", id: "1.apple"}
    1: Object {symbol: "orange", id: "1.orange"}
    2: Object {symbol: "fish", id: "2.fish"}
    3: Object {symbol: "pizza", id: "2.pizza"}
    4: Object {symbol: "red", id: "2.red"}
    5: Object {symbol: "grape", id: "3.grape"}
    6: Object {symbol: "apple", id: "3.apple"}
    __proto__: Array(0)

I'm having a heck of a time trying to filter on arrValues[0].symbol. I then need to append arrValues[0].id to the results. I figure createing a new object with arrProps and the unique ID would be best.

So in the case of apple, the first column should render {parent: arrProps[0], id: arrValues[0].id}, etc.

--- UPDATE ---

Rather than just showing the name of arrPorps[0].name, I need an object returned, as per the last line above (a change from the original question).

I had thought about finding some way to append arrProps to the output but got stuck there. Since I can hydrate the data model, I added some additional identifying properties to arrValues[] (wait, does this and arrProps[] really need to be an array, it's just an object - refactor?):

const arr = [
    { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ exchange: '1', symbol: 'apple', id: '1.apple' }, {exchange: '1', symbol: 'orange', id: '1.orange' }] },
    { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ exchange: '2', symbol: 'fish', id: '2.fish' }, { exchange: '2', symbol: 'pizza', id: '2.pizza' }, { exchange: '2', symbol: 'red', id: '2.red' }] },
    { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ exchange: '3', symbol: 'grape', id: '3.grape' }, { exchange: '3', symbol: 'apple', id: '3.apple' }] },
];

Then changed the output, creating an output object,

From: .map(({ arrProps }) => arrProps[0].name)

To: .map(({ arrValues }) => [{ exchange: arrValues[0].exchange, symbol: arrValues[0].symbol, id: arrValues[0].id }]);

Whole updated code:

    const arr = [
        { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ exchange: '1', symbol: 'apple', id: '1.apple' }, {exchange: '1', symbol: 'orange', id: '1.orange' }] },
        { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ exchange: '2', symbol: 'fish', id: '2.fish' }, { exchange: '2', symbol: 'pizza', id: '2.pizza' }, { exchange: '2', symbol: 'red', id: '2.red' }] },
        { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ exchange: '3', symbol: 'grape', id: '3.grape' }, { exchange: '3', symbol: 'apple', id: '3.apple' }] },
    ];
    
    const objectValues = arr.flatMap(({ arrValues }) => arrValues);  // not necessary if we refactor, removing these arrays?
    const values = objectValues.map(({ symbol }) => symbol);
    const uniqueValues = [...new Set(values)];
    const result = uniqueValues.reduce((acc, value) => {
        acc[value] = arr
            .filter(({ arrValues }) => {
                const symbols = arrValues.map(({ symbol }) => symbol)
                return symbols.includes(value);
            })
            //.map(({ arrProps }) => arrProps[0].name)
            .map(({ arrValues }) => [{ exchange: arrValues[0].exchange, symbol: arrValues[0].symbol, id: arrValues[0].id }]);
            //.join(',');
        return acc;
    }, {});
    
    console.log("RAW:" + JSON.stringify(result));
    
    console.log(result);
    console.table(result);
    
    Object.entries(result).forEach(([k, v]) => {
        console.log(`      ----] The value '${k}' exists in:`);
        console.table(JSON.stringify(v));
        //console.log("The pair: ", k)
        ////console.log("The value: ", v)
        v.forEach(_pool => console.log(`
            Exchange: ${_pool[0].exchange}
            symbol: ${_pool[0].symbol}
            ID: ${_pool[0].id}
        `));
    })

Two problems:

  1. I think the arrays are not necessary in the data model
  2. The output data is wrong.
{
   "apple":[
      [
         {
            "exchange":"1",
            "symbol":"apple",
            "id":"1.apple"
         }
      ],
      [
         {
            "exchange":"3",
            "symbol":"grape",   // should be "apple"
            "id":"3.grape"      // should be "3.apple"
         }
      ]
   ],
   "orange":[
      [
         {
            "exchange":"1",
            "symbol":"apple",   // should be "orange"
            "id":"1.apple"      // should be "1.orange"
         }
      ]
   ],
   "fish":[
      [
         {
            "exchange":"2",
            "symbol":"fish",
            "id":"2.fish"
         }
      ]
   ],
   "pizza":[
      [
         {
            "exchange":"2",
            "symbol":"fish",   // should be pizza
            "id":"2.fish"      // should be 2.pizza
         }
      ]
   ],
   "red":[
      [
         {
            "exchange":"2",
            "symbol":"fish",   // should be "red"
            "id":"2.fish"      // should be "2.red"
         }
      ]
   ],
   "grape":[
      [
         {
            "exchange":"3",
            "symbol":"grape",
            "id":"3.grape"
         }
      ]
   ]
}

--- UPDATE 2 ---

Going back to my suspicion of the data being wrong, well, it appears to be.

Rather than each object being named according to its related common word: apple, orange, fish, this needs to be parameterized and superfluous arrays removed (pseudocoded object):

[{
    itemName: 'apple',
    itemParam2: 'xxx',
    itemPools: [
        { source: '3', symbol: 'apple', id: '3.apple', cost: '0.00' },
        { source: '4', symbol: 'apple', id: '4.apple', cost: '0.00' },
        { source: '4', symbol: 'apple', id: '4b.apple', cost: '0.00' }
      ],
    itemName: 'orange',
    itemParam2: 'yyy',
    itemPools: [
    ...
    itemName: 'fish',
    itemParam2: 'zzz',
    itemPools: [
    ...
}]

FYI: need to verify the result data object to be properly formatted

Actually, orange and fish should be omited from the model as the itemPools.length is not > 1.

So in addition to the updated model properties, only items where itemPool.length > 1 should be added.

Without this, I am unable to find an array item by its property.

To give some future context, here.

1 Answer 1

1

After several approaches, I changed solution. In my opinion, it is now simpler and more versatile.

const arr = [
    { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ symbol: 'apple', id: '1.apple' }, {symbol: 'orange', id: '1.orange'}] },
    { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ symbol: 'fish', id: '2.fish' }, { symbol: 'pizza', id: '2.pizza' }, { symbol: 'red', id: '2.red' }] },
    { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ symbol: 'grape', id: '3.grape'}, { symbol: 'apple', id: '3.apple' }] },
];

const result = arr.reduce((acc, { arrProps: [{ name }], arrValues }) => {
    arrValues.map(({ symbol }) => symbol)
    .forEach((value) => {
        acc[value] = acc[value] ? `${acc[value]},${name}`: name;
    });
    return acc;
}, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If we consider the previous approach with the filter, the solution could be as follows:

const arr = [
    { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ symbol: 'apple', id: '1.apple' }, {symbol: 'orange', id: '1.orange'}] },
    { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ symbol: 'fish', id: '2.fish' }, { symbol: 'pizza', id: '2.pizza' }, { symbol: 'red', id: '2.red' }] },
    { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ symbol: 'grape', id: '3.grape'}, { symbol: 'apple', id: '3.apple' }] },
];

const objectValues = arr.flatMap(({ arrValues }) => arrValues);
const values = objectValues.map(({ symbol }) => symbol);
const uniqueValues = [...new Set(values)];
const result = uniqueValues.reduce((acc, value) => {
  acc[value] = arr
    .filter(({ arrValues }) => {
      const symbols = arrValues.map(({ symbol }) => symbol)
      return symbols.includes(value);
    })
    .map(({ arrProps }) => arrProps[0].name)
    .join(',');
  return acc;
}, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

---UPDATE---

const arr = [
        { arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ exchange: '1', symbol: 'apple', id: '1.apple' }, {exchange: '1', symbol: 'orange', id: '1.orange' }] },
        { arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ exchange: '2', symbol: 'fish', id: '2.fish' }, { exchange: '2', symbol: 'pizza', id: '2.pizza' }, { exchange: '2', symbol: 'red', id: '2.red' }] },
        { arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ exchange: '3', symbol: 'grape', id: '3.grape' }, { exchange: '3', symbol: 'apple', id: '3.apple' }] },
    ];
    
    
const result = arr.reduce((acc, { arrValues }) => {
    arrValues.forEach((value) => {
        acc[value.symbol] = acc[value.symbol] 
          ? [...acc[value.symbol], value] 
          : [value]; 
    });
    return acc;
}, {});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

---UPDATE 3---

const arr = [
{ arrProps: [{ name: '1', prop2: 'aaa' }], arrValues: [{ exchange: '1', symbol: 'apple', id: '1.apple' }, {exchange: '1', symbol: 'orange', id: '1.orange' }] },
{ arrProps: [{ name: '2', prop2: 'bbb' }], arrValues: [{ exchange: '2', symbol: 'fish', id: '2.fish' }, { exchange: '2', symbol: 'pizza', id: '2.pizza' }, { exchange: '2', symbol: 'red', id: '2.red' }] },
{ arrProps: [{ name: '3', prop2: 'ccc' }], arrValues: [{ exchange: '3', symbol: 'grape', id: '3.grape' }, { exchange: '3', symbol: 'apple', id: '3.apple' }] },
];

const reduceArray = (data, poolsCountEdge = 1) => {
  const result = data.reduce((acc, { arrValues }) => {
      arrValues.forEach((value) => {
         const item = acc.find(({ name }) => name === value.symbol);
         if (item) {
           item.pools.push(value);
           item.poolsCount = item.pools.length;
         } else {
           acc.push({ name: value.symbol, poolsCount: 1, pools: [value] }); 
         }
      });
      
      return acc;
  }, []);
  
  return result.filter(({ poolsCount }) => poolsCount > poolsCountEdge)
};

console.log(reduceArray(arr));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

9 Comments

Rather than just a string of .name in the matching outputs, I need an object that contains additional properties. I refactored the code and data model to include these but appear to be stuck once more. Please see after ---UPDATE--- above.
@ElHaix Updated solution to reflect new object structure. See ---UPDATE--- section.
This is great, thank you. One last thing: I only want to add to the model if there a symbol appears more than once - something like if symbol.count > 1 ?
@ElHaix Please post the object model you would like to have.
@ElHaix Check ---UPDATE 2--- section. Now result is not an object but array of objects. You can easily do all array's manipulation: filter, map, find and so on.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.