2017-06-01 93 views
0

我正在使用以下函數來解析csv文件。將第一個屬性轉換爲鍵

export default function readCsv (csv, reviver) { 
 
    reviver = reviver || function(r, c, v) { 
 
    return v; 
 
    }; 
 
    let chars = csv.split(''), 
 
    c = 0, 
 
    cc = chars.length, 
 
    start, end, table = [], 
 
    row; 
 
    while (c < cc) { 
 
    table.push(row = []); 
 
    while (c < cc && '\r' !== chars[c] && '\n' !== chars[c]) { 
 
     start = end = c; 
 
     if ('"' === chars[c]) { 
 
     start = end = ++c; 
 
     while (c < cc) { 
 
      if ('"' === chars[c]) { 
 
      if ('"' !== chars[c + 1]) { 
 
       break; 
 
      } else { 
 
       chars[++c] = ''; 
 
      } // unescape "" 
 
      } 
 
      end = ++c; 
 
     } 
 
     if ('"' === chars[c]) { 
 
      ++c; 
 
     } 
 
     while (c < cc && '\r' !== chars[c] && '\n' !== chars[c] && ',' !== chars[c]) { 
 
      ++c; 
 
     } 
 
     } else { 
 
     while (c < cc && '\r' !== chars[c] && '\n' !== chars[c] && ',' !== chars[c]) { 
 
      end = ++c; 
 
     } 
 
     } 
 
     row.push(reviver(table.length - 1, row.length, chars.slice(start, end).join(''))); 
 
     if (',' === chars[c]) { 
 
     ++c; 
 
     } 
 
    } 
 
    if ('\r' === chars[c]) { 
 
     ++c; 
 
    } 
 
    if ('\n' === chars[c]) { 
 
     ++c; 
 
    } 
 
    } 
 
    return table; 
 
}

JSON的是這樣的:

enter image description here

我想JSON是什麼樣子如下:

[ 
    doc_id: "16278", 
    framework_id: "8078", 
    ... 
], 
[ 
    doc_id: "16261", 
    framework_id: "880", 
    ... 
], 

基本上,代替得到杉木st行的內容作爲json中的第一個值,第一行應該被轉換成鍵,其餘行被轉換爲值。

+2

請郵寄樣本數據,而不是它的照片的 – baao

+0

留下您的CSV閱讀功能,因爲它是 - 後處理的數據把它所需格式 – Alnitak

+1

將按鍵的其餘像'what_is_this_document','when_would_i_use_this_document' ,'who_signs_this_document','more_details_about_this_document','what_are_the_core_elements_of_this_document'和'related_documents'? –

回答

3

這是比較瑣碎,處理後的數據,將其映射到所需的格式,即給出從CSV閱讀器的輸出變量data

data = data.slice(1).map(function(row) { 
    return row.reduce(function(obj, value, index) { 
     var key = data[0][index]; // extract from first original row 
     obj[key] = value; 
     return obj; 
    }, {}); 
}); 

即遍歷所有行(跳過1日) ,根據第零行的鍵和當前的值創建一個對象。

請注意,這將使用長格式的原始鍵。你可能希望改變第一行中的值,使之更規範化的第一,如:

data[0] = data[0].map(function(key) { 
    key = key.replace(/[^\w\d\s]/g, ''); // strip non-alphanum or space 
    return key.replace(/\s/g, '_').toLowerCase(); 
}); 
+0

因此,從csv映射json不是執行此類任務的最佳方法嗎? – AnAspiringCanadian

+1

您沒有「JSON」,這是對象序列化格式,就像CSV是數據格式一樣。如果你已經有CSV,那麼你最好的選擇(每個上面)是使用一個對你的預期結構一無所知的沼氣標準CSV閱讀器,然後把數據操作到所需的結構。 – Alnitak

+0

我的錯誤,不知道爲什麼我指的是一個簡單的數組作爲json。 – AnAspiringCanadian

-1

試試這個:

const csvData = ` 
    id,first_name,last_name,email,gender,ip_address 
    1,Jami,Dumingos,[email protected],Female,209.112.103.56 
    2,Brenda,Harbach,[email protected],Female,160.201.233.94 
    3,Gail,Rowbrey,[email protected],Female,160.199.58.40 
    4,Ludvig,Coil,[email protected],Male,158.37.136.163 
    5,Lurlene,Conochie,[email protected],Female,145.147.12.44 
    6,Aldous,Farrey,[email protected],Male,44.148.54.88 
    7,Skipp,Sket,[email protected],Male,81.190.215.227 
    8,Greg,Wakefield,[email protected],Male,105.157.167.96 
    9,Westley,Purton,[email protected],Male,169.67.113.22 
    10,Dill,Avraam,[email protected],Male,223.60.54.101`; 

function readCsv(csv, splitMark = ',') { 
    const lines = csv.split('\n'); 
    const keys = lines[0].split(splitMark); // first line as heading 
    const rows = lines.slice(1, lines.length - 1); 

    return rows.map(row => row 
    .split(splitMark) 
    .reduce((map, col, index) => { 
     map[keys[index]] = col; 
     return map; 
    }, { })); 
} 

readCsv(csvData); 
+0

您的CSV閱讀不像OP那樣具有彈性(或有特色)。 – Alnitak

+0

am同意與你@Alnitak – embarq

+0

csvs會有段落,所以我不能用換行符作爲參數來拆分內容。 – AnAspiringCanadian

0

這是一種有效的方法:

function csvToKeyedArray(csv) { 
    var data = []; 
    var keys = csv[0]; 
    var datum, entry, index; 

    for (index in keys) { 
    keys[index] = keys[index] 
     .replace(/[^\w ]+/g, '') // remove extraneous characters like '?' 
     .replace(/ /g, '_') // replace spaces with _ 
     .toLowerCase(); 
    } 

    for (entry = 1; entry < csv.length; entry++) { 
    // initialize an object for each row and add it to the `data` array 
    data[entry - 1] = datum = {}; 

    for (index in keys) { 
     // convert rows to objects 
     datum[keys[index]] = csv[entry][index]; 
    } 
    } 

    return data; 
} 

data然後填充到您的規格。

如果您的CSV文件包含10000行,則優於使用.map(),因爲由於每次迭代的函數調用導致的上下文切換開銷會導致明顯變慢。

但是,如果您的CSV文件預計只有幾百或幾千行,那麼使用.map()可能更適合可讀性和可維護性。

+0

FWIW,我會剛剛使用'data.push(datum)'而不是'data [entry-1] = datum' ... – Alnitak

+0

@Alnitak在效率方面,避免函數調用更可取。就像我說的,如果可讀性和可維護性比效率更重要,我推遲到你的答案。是的,這是一個微型優化,但它確實與我所描述的數量級的大型CSV文件有很大的差別。 –

+0

(特指推送)這似乎是(假)微優化給我... https://stackoverflow.com/questions/21034662/why-push-method-is-significantly-slower-than-putting - 值-通路陣列指數式 – Alnitak