Как проверить, существует ли в объекте несколько свойств?

#javascript

Вопрос:

У меня есть объект result , который можно получить, например:

 const firstRowVoucher = result[0]['Voucher ID'] || result[0]['voucher_id'] || result[0]['VOUCHER_ID'];
const firstRowInvoice = result[0]['Invoice'] || result[0]['INVOICE'] || result[0]['invoice'];

if (firstRowVoucher amp;amp; firstRowInvoice){
  //do some code
}

result.forEach((element) => {
  const elementVoucher =  element['Voucher ID'] || result[0]['voucher_id'] || element['VOUCHER_ID'];
  const elementStatus =  element['Invoice'] || result[0]['INVOICE'] || element['invoice'];
 
  if(elementVoucher amp;amp; elementStatus){
    // do some other stuff
  }
});
 

Это работает, но кажется немного запутанным, потому что есть много других слов и условий.

Есть ли способ проверить в списке names , имеет ли объект эти names атрибуты в качестве атрибутов? Для того, чтобы получить лучшее обслуживание и лучшую читабельность.

Возможно, используя массив объектов или что-то в этом роде:

  const fields = {
    unit: ['Unit' || 'unit' || 'UNIT'],
    voucherID: ['Voucher ID' || 'voucher_id' || 'VOUCHER_ID'],
    invoice: ['Invoice' || 'INVOICE' || 'invoice'],
    status: ['status' || 'STATUS' || 'Status'],
    invoiceGrossAmount: [
      'Invoice Gross Amount' ||
        'Invoice_Gross_Amount' ||
        'invoice gross amount' ||
        'invoice_gross_amount',
    ],
    currency: ['Currency' || 'currency'],
    SupplierID: [
      'Supplier ID' || 'supplier_id' || 'Supplier_Id' || 'Supplier_ID',
    ],
    PONumber: ['PO Number' || 'PO_Number' || 'po_number' || 'po number'],
    status: ['status' || 'Status' || 'STATUS'],
  };

 

Я не знаю, как поступить дальше.

Комментарии:

1. Есть ли у вас доступ к «результату»? В идеале эти ключи должны быть стандартизированы

2. Спасибо! Не идеально, если эти результаты получены из импортированного файла и могут изменяться в разных форматах из одного и того же типа файла. это большие файлы.

3. Если вы хотите только проверить, существует ли ключ внутри объекта , вы можете использовать Object.keys(your-object) , чтобы создать массив со всеми ключами внутри объекта, а затем использовать .some(key => key.toLowerCase() === <seach-string>.toLowerCase()) . Сделав это, вы переведете все ключи внутри массива в нижний регистр, а затем также сравните их со строкой поиска в нижнем регистре. Но, как сказал Габриэль в комментарии выше, возможно, вы сможете точно знать, какие ключи вы получите в результате, и сделать это немного проще. Вы также можете заменить _ любого другого персонажа, если хотите

4. В вашем .forEach() цикле, почему вы проверяете элемент на наличие одних значений и result[0] на наличие других значений?

Ответ №1:

Я бы рекомендовал преобразовать ваши объекты результатов в один определенный формат. Одним из способов добиться этого было бы установить все ваши ключи в snake_case

 const snakeCaseResults = result.map((obj) =>
  Object.entries(obj).reduce(
    (res, [key, value]) => ({ ...res, [key.toLowerCase().replaceAll(' ', '_')]: value }),
    {}
  )
)
 

таким образом, вы всегда можете получить доступ к своему результату с помощью snake_case

Напр.

 const firstRowVoucher = snakeCaseResults[0]['voucher_id'];
const firstRowInvoice = snakeCaseResults[0]['invoice'];
 

Комментарии:

1. @dMd — Смотрите мой ответ выше, в котором несколько пробелов сворачиваются в одно каноническое пространство перед сравнением.

2. Я просто изменил эту строку, чтобы она соответствовала всем пробелам. [ключ.в нижнем регистре().заменить(/ /g, ‘ ‘).заменить(‘ ‘, ‘_’)]: значение,

Ответ №2:

Вы можете создать небольшую вспомогательную функцию, которая проверяет различные версии для вас, чтобы у вас был только этот код в одном месте:

 // pass any case example with optional space or underline
function getField(obj, example) {
    // create canonical lowerCase version with single space delimiters
    const exSpace = example.replace(/s |_ /g, " ").toLowerCase();
    let props = Object.entries(obj);
    for (let propName of props) {
        // take candicate property name and convert it to canonical
        // form of lowercase, space delimited, spaces and underscores collapsed
        const propCanonical = propName.toLowerCase().replace(/s |_ /g, " ");
        if (propCanonical === exSpace) {
            return obj[propName];
        }
    }
    return null;        
}
 

А затем используйте его вот так:

 const firstRowVoucher = getField(result[0], 'Voucher ID');
const firstRowInvoice = getField(result[0], 'Invoice');
 

К вашему сведению, сам факт того, что вы не знаете, какова форма имени поля, кажется каким-то плохим кодом где — то до этого, который следует очистить. Если у вас действительно нет контроля над качеством ввода, то , возможно, вам следует просто очистить весь ввод, прежде чем обрабатывать его, чтобы, как только вы получите result , использовать только стандартизированные имена полей.