0

How to get the object value based on combinations in javascript?

I Don't know how to iterate over the object based on inputs given to the function call and get the object value. Need some help.

Expected output should be as shown below.

getValueCreditToBank(obj, "credit", "bank", "SGD");
getValueDebitToBank(obj, "debit", "bank", "THB");

Below code gets the value but have to do two functions, is there any method to do in single function call,

// getValueCreditToBank(obj, "credit", "bank", "SGD");
function getValueCreditToBank(provider, typein, typeout, source){
  return provider.map(item => {
    if (item.country_from[0].paymentIn[0].type == typein 
        && item.country_from[0].currency.includes(source) 
        && item.country_from[0].paymentOut[0].type == typeout) {
      return {
        paymentIn: typein,
        paymentOut: typeout,
        paymentInFee: item.country_from[0].paymentIn[0].fee.number + "%",
        payInSpeed: item.country_from[0].paymentIn[0].speed.number + "days",
        ...item
      }      
    }
   })
  .map(y=>({  
    ...y,
    targetAmountwithPay: y.targetAmount + y.country_from[0].paymentIn[0].fee.number*y.targetAmount/100
  }))
}

// getValueDebitToBank(obj, "debit", "bank", "SGD");
function getValueDebitToBank(provider, typein, typeout, source){
  return provider.map(item => {
    if (item.country_from[0].paymentIn[1].type == typein 
        && item.country_from[0].currency.includes(source) 
        && item.country_from[0].paymentOut[0].type == typeout) {
      return {
        paymentIn: typein,
        paymentOut: typeout,
        paymentInFee: item.country_from[0].paymentIn[1].fee.number + "%",
        payInSpeed: item.country_from[0].paymentIn[1].speed.number + "days",
        ...item
      }      
    }
   })
  .map(y=>({  
    ...y,
    targetAmountwithPay: y.targetAmount + y.country_from[0].paymentIn[0].fee.number*y.targetAmount/100
  }))
}

Example of the object:

var obj = [{
    "id": "identity1",
    "fee": '2',
    "rate": '0.5',
    "targetAmount": '1000',
     "country_from": [{
        "currency": [
            "SGD",
            "USD"
        ],
        "paymentIn": [{
            "type": "credit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1.5"
            }
        },{
            "type": "debit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1"
            }
        }],
       "paymentout":[{
          "type":"bank"
       }]
    }]
},
{
    "id": "identity2",
    "fee": '1',
    "rate": '0.5',
    "targetAmount": '1000',
     "country_from": [{
        "currency": [
            "THB",
            "USD"
        ],
        "paymentIn": [{
            "type": "debit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1"
            }
        }
        ],
       "paymentout":[{
          "type":"bank"
       }]
    }]
}]

Expected Output:

//getValue(obj, "credit", "bank", "SGD"); should return object as
 {id: "identity1",
 fee: '2',
 rate: '0.5',
 currency: SGD,
 paymentIn: "credit",
 paymentOut: "bank",
 paymentIn Fee: 1.5%,
 targetAmount: 1000,
 targetAmountwithPay: 506.485 //(((targetamount-fee)*rate)+credit fee))}
//getValue(obj, "debit", "bank", "THB"); should return object as
 {id: "identity2",
 fee: '1',
 rate: '0.5',
 currency: THB,
 paymentIn: "debit",
 paymentOut: "bank",
 paymentIn Fee: 1%,
 targetAmount: 1000,
 targetAmountwithPay: 504.49 //(((targetamount-fee)*rate)+credit fee))}
11
  • what if country_from array has more than one obj? Commented Apr 2, 2019 at 7:34
  • @AswinKumar thanks for prompt reply based on currency("SGD") have to filter it and do the combination, like for each typein(credit, debit) and typeout(bank), should calculate the targetamount and return the object as shown Commented Apr 2, 2019 at 7:38
  • @AswinKumar i have updated the code, if possible please share answer.thanks Commented Apr 2, 2019 at 9:09
  • How can we provide fee and rate in your output? The same for finding the amount. I don't find where you have to take these information from your original object. And why are there array with only one object inside? Commented Apr 2, 2019 at 9:24
  • @iArcadia apologies, updated the code obj Commented Apr 2, 2019 at 9:35

2 Answers 2

1

The first issue I see with your code is that you map on all the array but you only change some elements.

Maybe you didn't notice this because the filter you set is passing all the array elements, but in case it doesen't, than you will see many undefined in your final array.

So I suggest you to update your code introducing a filter:

function getValueCreditToBank(provider, typein, typeout, source){
  return provider
    .filter(item => (item.country_from[0].paymentIn[0].type == typein 
        && item.country_from[0].currency.includes(source) 
        && item.country_from[0].paymentOut[0].type == typeout))
    .map(item => ({
        paymentIn: typein,
        paymentOut: typeout,
        paymentInFee: item.country_from[0].paymentIn[0].fee.number + "%",
        payInSpeed: item.country_from[0].paymentIn[0].speed.number + "days",
        ...item
      }))
  .map(y=>({  
    ...y,
    targetAmountwithPay: y.targetAmount + y.country_from[0].paymentIn[0].fee.number*y.targetAmount/100
  }))
}

You do the almost the same task in both function, and you don't use parameter properly, so for example you can determine the index of paymentIn by typein parameter:

function getValueToBank(provider, typein, typeout, source){
  const paymentInIndex = typein === 'credit' ? 0 : 1;
  return provider
    .filter(item => (item.country_from[0].paymentIn[paymentInIndex].type == typein 
        && item.country_from[0].currency.includes(source) 
        && item.country_from[0].paymentOut[0].type == typeout))
    .map(item => ({
        paymentIn: typein,
        paymentOut: typeout,
        paymentInFee: item.country_from[0].paymentIn[paymentInIndex].fee.number + "%",
        payInSpeed: item.country_from[0].paymentIn[paymentInIndex].speed.number + "days",
        ...item
      }))
}

And then you can implment your function:

function getValueCreditToBank(provider, typeout, source){
    return getValueToBank(provider, 'credit', typeout, source)
    .map(y=>({  
        ...y,
        targetAmountwithPay: y.targetAmount + y.country_from[0].paymentIn[0].fee.number*y.targetAmount/100
  }))
}

function getValueDebitToBank(provider, typeout, source){
    return getValueToBank(provider, 'debit', typeout, source)
}

So you remove the typein parameter from your original functions as it is determined by the function name.

This is just an example, you can rewrite in differet ways, a much readable would be to give a name to the arrow functions you pass to filter and map the array.

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

Comments

0

Here's three functions :

  • getValue(obj, pin, pout, currency) is the one which do aaaall the logic.
  • getValueCreditToBank(obj, currency) is a shorthand for getValue(obj, 'credit', 'bank', currency).
  • getValueDeditToBank(obj, currency) is a shorthand for getValue(obj, 'debit', 'bank', currency).

The function currently works only if the country_from array has one object.

Logic is simple:

  • Find in the object array the one which have a corresponding paymentIn and paymentOut object, and a corresponding currency.
  • If a corresponding object is found:
    • Calculate targetAmountWithPay.
    • Return a new object.

/**
 * Shorthand for getValue() with {pin = "credit"} and {pout = "bank"}.
 * @param {Object[]} obj
 * @param {string} currency
 * @returns {Object}
 */
function getValueCreditToBank(obj, currency) {
  return getValue(obj, 'credit', 'bank', currency);
}

/**
 * Shorthand for getValue() with {pin = "debit"} and {pout = "bank"}.
 * @param {Object[]} obj
 * @param {string} currency
 * @returns {Object}
 */
function getValueDebitToBank(obj, currency) {
  return getValue(obj, 'debit', 'bank', currency);
}

/**
 * @param {Object[]} obj
 * @param {string} pin
 * @param {string} pout
 * @param {string} currency
 * @returns {Object}
 */
function getValue(obj, pin, pout, currency) {
  // paymentIn and paymentOut corresponding objects found from function parameters, initialized to undefined.
  let opint, opout;
  
  // The corresponding item found from function parameters.
  const found = obj.find((item) => {
    // Gets paymentIn object from pin parameter.
    opin = item.country_from[0].paymentIn.find((pinItem) => (pinItem.type.indexOf(pin) > -1));
    
    // Gets paymentOut object from pout parameter.
    opout = item.country_from[0].paymentout.find((poutItem) => (poutItem.type.indexOf(pout) > -1));
    
    // If no paymentIn object, or no paymentOut object, or no currency found,
    // we cannot find anything.
    if (item.country_from[0].currency.indexOf(currency) === -1 || !opin || !opout) {
      return false;
    }
    
    return true;
  });
  
  // If a corresponding object is found, creates the returned object.
  if (found) {
    let targetAmountWithPay = (found.targetAmount - found.fee) * found.rate;
    targetAmountWithPay += opin.fee.number * targetAmountWithPay / 100;
  
    return {
      id: found.id,
      fee: parseFloat(found.fee),
      rate: parseFloat(found.rate),
      currency: currency,
      paymentIn: pin,
      paymentOut: pout,
      paymentInFee: `${opin.fee.number}${opin.fee.type}`,
      targetAmount: parseFloat(found.targetAmount),
      targetAmountWithPay: targetAmountWithPay
    };
  }
  
  // If not, returns null.
  return null;
}

// Tests you gave us.
console.log(getValueCreditToBank(obj, 'SGD'));
console.log(getValueDebitToBank(obj, 'THB'));

// Test if nothing is found. Should return null.
console.log(getValueCreditToBank(obj, 'EUR'));
console.log(getValueDebitToBank(obj, 'EUR'));
console.log(getValue(obj, 'credit', 'not-a-bank', 'SGD'));
console.log(getValue(obj, 'not-a-credit-nor-a-debit', 'bank', 'SGD'));
<script>
// I put your object in HTML in order to have two different frames in the snippet.
const obj = [{
    "id": "identity1",
    "fee": '2',
    "rate": '0.5',
    "targetAmount": '1000',
     "country_from": [{
        "currency": [
            "SGD",
            "USD"
        ],
        "paymentIn": [{
            "type": "credit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1.5"
            }
        },{
            "type": "debit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1"
            }
        }],
       "paymentout":[{
          "type":"bank transfer"
       }]
    }]
},
{
    "id": "identity2",
    "fee": '1',
    "rate": '0.5',
    "targetAmount": '1000',
     "country_from": [{
        "currency": [
            "THB",
            "USD"
        ],
        "paymentIn": [{
            "type": "debit",
            "speed": {
                "unit": "days",
                "number": "1"
            },
            "fee": {
                "type": "%",
                "number": "1"
            }
        }
        ],
       "paymentout":[{
          "type":"bank transfer"
       }]
    }]
}];
</script>

If you want an answer with an update of functions you tried to do yourself, check @Mario Santini's answer.

Comments

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.