L oop через массив с объектами с необязательными свойствами, но всегда l oop полностью - PullRequest
0 голосов
/ 13 февраля 2020

Я хочу перебрать массив объектов, определенных следующим образом:

export interface Incident {
  ID: string;
  userName1?: string;
  userName2?: string;
  userPhoneNumber?: string;
  crashSeverity: number;
  crashTime: number;
}

Теперь у меня есть несколько примеров данных, таких как:

  {
    crashID: "CO111111",
    userName1: "TEST",
    userName2: "NAME2",
    userPhoneNumber: "11111",
    crashSeverity: 2,
    crashTime: 1571566666
  },
  {
    crashID: "12345",
    userName1: "TEST",
    crashSeverity: 2,
    crashTime: 1571566666
  }

Однако я хочу сохранить данные в CSV-файл. Для этого мне нужно всегда перебирать весь интерфейс, даже если некоторые свойства отсутствуют, и по-прежнему писать запятую. Есть ли способ перебора всего интерфейса инцидента для каждого объекта, а не только всех доступных свойств?

Вот пример выходных данных: enter image description here

My текущий код:


  ConvertToCSV(objArray) {
    const array =
      typeof objArray !== "object" ? JSON.parse(objArray) : objArray;
    let str = "";
    let header = "";

    for (const index in objArray[0]) {
      header += index + ";";
    }
    header = header.slice(0, -1);
    // append Label row with line break
    str += header + "\r\n";

    // loop through every entry
    for (let i = 0; i < array.length; i++) {
      let line = "";
      // loop through every row
      for (const firstIndex in array[i]) {
          line += array[i][firstIndex] + ";";
      }
      str += line + "\r\n";
    }
    return str;
  }

Ответы [ 2 ]

1 голос
/ 17 февраля 2020

Интерфейсы существуют только во время компиляции. Они не существуют во время выполнения, поэтому вы не можете проверить их с помощью кода.

Без этой возможности вы все равно могли бы что-то сделать, чтобы хотя бы убедиться, что выходной CSV правильно сформирован, то есть все значения отображаются в их правый столбец.

Для этого вам необходимо сначала проверить все данные и собрать все используемые поля. Когда полей часто не хватает, вам понадобится лог c для получения правильного порядка полей. Например, если у вас есть два объекта, и у первого есть только поля «a» и «b», а у второго только поля «c» и «d», нет способа узнать правильный порядок полей. Это может быть "a; b; c; d", или "a; c; b; d" или "c; a; b; d", ... et c. Однако, если есть и третий объект, имеющий поля «b» и «c», то порядок определен совершенно точно: «a; b; c; d». Речь идет о поиске топологического порядка .

Итак, вот код, который сначала выполняет такое сканирование и упорядочение, а затем приступает к фактическому кодированию данных в виде CSV во второй фазе:

function convertToCSV(objArray) {
    const array =
        typeof objArray === "string" ? JSON.parse(objArray) : objArray;
    
    // Iterate the whole array to find any fields
    //    Keep track of which fields have to precede other fields
    const predecessors = new Map;
    for (const obj of array) {
        Object.keys(obj).forEach((key, i, keys) => {
            if (!predecessors.has(key)) predecessors.set(key, new Set);
            if (i) predecessors.get(key).add(keys[i-1]);
        });
    }
    // Sort fields
    const fields = topologicalSort(predecessors);

    return [fields.join(";"), // header line
        ...array.map(obj => fields.map(field => obj[field] || "").join(";")) // data lines
    ].join("\r\n");
}

function topologicalSort(predecessors) {
    const visited = new Set;
    
    function visit(key) {
        if (visited.has(key)) return;
        predecessors.get(key).forEach(visit);
        visited.add(key);
    }
    
    for (let key of predecessors.keys()) visit(key);
    return [...visited];
}

// Sample data
const data = [{
    userName2: "NAME2",
    userPhoneNumber: "11111",
    crashSeverity: 2,
  }, {
    userName1: "TEST",
    crashSeverity: 2,
    crashTime: 1571577777
  }, {
    crashID: "12345",
    userName1: "Mr First",
    userName2: "Second name",
    crashSeverity: 3,
    crashTime: 1571588888
  }];

const csv = convertToCSV(data);
console.log(csv);
0 голосов
/ 21 февраля 2020

Я решил это, сохранив заголовки в .ts и просто получив доступ к значениям через имена заголовков:

  headers = [
"crashID",
"userName1",
"userName2",
"userPhoneNumber",
"crashSeverity",
"crashTime"
];

ConvertToCSV(objArray) {
const array =
  typeof objArray !== "object" ? JSON.parse(objArray) : objArray;
let str = "";
const header = this.headers.join(";");
str += header + "\r\n";

// loop through every entry
for (let i = 0; i < array.length; i++) {
  let line = "";
  // loop through every row
  for (const headerElem of this.headers) {
    line += array[i][headerElem];
    line += ";";
  }
  str += line + "\r\n";
}
return str;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...