Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
108 views
in Technique[技术] by (71.8m points)

javascript - JS: How to filter an array of objects, add to the first object a key with values of the rest of filtered elements?

I am trying to implement in Tabulator JS an opportunity for user to reconstruct from a table a new one with tree structure. So tableData is an assumed table and columnTree is user's choice which column has to be the tree root.

My idea is firstly to store unique key values in an array, then loop through the tableData filtering it by each key, add to the first element [_children] key with values of the rest of the filtered objects.

var columnTree = "continent";

var tableData = [
                {continent:"Asia", country:"China"},
                {continent:"Asia", country:"Vietnam"},
                {continent:"Asia", country:"Thai"},
                {continent:"America", country:"USA"},
                {continent:"America", country:"Canada"},
                {continent:"Africa", country:"Egypt"},
                {continent:"Africa", country:"Somalia"},
            ];

Get unique keys

var unique = tableDataNested.map(item => item[columnTree]).filter((value, index, self) => self.indexOf(value) === index);

//?["Asia", "America", "Afrika"]

Filter function

function filterByValue(array, string) {
                return array.filter(o =>
                    Object.keys(o).some(k => o[k].toLowerCase().includes(string.toLowerCase())));
            };

The last step

var finalArray = [];
unique.forEach(function(continent) {
                //temporary array with values of each continent 
                var tempArray = filterByValue(tableDataNested, continent);
                console.log(tempArray);
                //get the first object
                console.log(tempArray[0]);
                //add to the first object '_children' key with values of the rest of objects except the 
                //first.
                var finalResult = tempArray[0]['_children'] = [tempArray.slice(1)];
                console.log(finalResult);
                finalArray.push(finalResult);
            });

The thing is, it crashes on the second continent and I can't get why

VM480:3 Uncaught TypeError: o[k].toLowerCase is not a function
    at <anonymous>:3:51
    at Array.some (<anonymous>)
    at <anonymous>:3:36
    at Array.filter (<anonymous>)
    at filterByValue (<anonymous>:2:30)
    at <anonymous>:2:33
    at Array.forEach (<anonymous>)
    at <anonymous>:1:8

My ideal result is

var finalArray = [
                {continent:"Asia", country:"China", "_children": [
                    {continent:"Asia", country:"Vietnam"},
                    {continent:"Asia", country:"Thai"}
                ]},
                {continent:"America", country:"USA", "_children": [
                    {continent:"America", country:"Canada"},
                ]},
                {continent:"Africa", country:"Egypt",  "_children": [
                    {continent:"Africa", country:"Somalia"}
                ]}
            ];
question from:https://stackoverflow.com/questions/65839980/js-how-to-filter-an-array-of-objects-add-to-the-first-object-a-key-with-values

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You might be better off using a generic groupBy function, for example

function groupBy(ary, fn) {
    let m = new Map();
    for (let x of ary) {
        let key = fn(x);
        if (!m.has(key))
            m.set(key, []);
        m.get(key).push(x);
    }
    return m;
}

and then

let groupMap = groupBy(tableData, x => x[columnTree]);
let result = [];

for (let [first, ...rest] of groupMap.values()) {
    first._children = rest;
    result.push(first);
}

Note that this also mutates the original tableData array, if this is not desirable, change the loop body to:

result.push({...first, _children: rest});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...