数据清洗问题

 1.常规数组扁平化

多维数组:
let arr = [
    [1, 2, 2],
    [3, 4, 5, 5],
    [6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
    10
];

 方案1:基于ES10中新增的flat实现扁平化处理 
 let flatArr = arr.flat(Infinity);
 console.log(flatArr);

 方案2:基于concat方式进行逐级降维 
 while (
    arr.some(function (item) {
        return Array.isArray(item);
    })
) {
    // arr = [].concat(...arr);
    arr = [].concat.apply([], arr);
}
console.log(arr); 

 方案3:执行toString变为字符串的时候就已经扁平化了「不适合某一项是对象,因为对象会变为“[object Object]”」 
 arr = arr.toString().split(',').map(function (item) {
    return +item;
});
console.log(arr); 

 方案4:基于递归实现 
Object.defineProperty(Array.prototype, 'myFlat', {
    writable: true,
    configurable: true,
    enumerable: false,
    value: function myFlat() {
        var result = [];
        var next = function next(arr) {
            arr.forEach(function (item) {
                if (Array.isArray(item)) {
                    next(item);
                    return;
                }
                result.push(item);
            });
        };
        next(this);
        return result;
    }
});
var flatArr = arr.myFlat();
console.log(flatArr);

2.特殊数组扁平化

let address = [{
    "code": "11",
    "name": "北京市",
    "children": [{
        "code": "1101",
        "name": "市辖区",
        "children": [{
            "code": "110101",
            "name": "东城区"
        }, {
            "code": "110102",
            "name": "西城区"
        }]
    }]
}, {
    "code": "13",
    "name": "河北省",
    "children": [{
        "code": "1301",
        "name": "石家庄市",
        "children": [{
            "code": "130102",
            "name": "长安区"
        }, {
            "code": "130104",
            "name": "桥西区"
        }]
    }, {
        "code": "1302",
        "name": "唐山市",
        "children": [{
            "code": "130202",
            "name": "路南区"
        }, {
            "code": "130203",
            "name": "路北区"
        }]
    }]
}];

 方案1:递归查找「深度优先原则」 
 const getNameByCode = function getNameByCode(address, code) {
    let result = "";
    const next = arr => {
        for (let i = 0; i < arr.length; i++) {
            let { code: codeItor, name, children } = arr[i];
            if (codeItor == code) {
                result = name;
                break;
            }
            if (Array.isArray(children)) next(children);
        }
    };
    next(address);
    return result;
} 
console.log(getNameByCode(address, '130102')); //"长安区"
console.log(getNameByCode(address, '1302')); //"唐山市"

先把数组扁平化,后期查找的时候按照扁平化的数组查找即可 
const getNameByCode = (function (address) {
    // 先扁平化处理「广度优先原则」
    let result = [];
    const next = arr => {
        // 先把本级处理好
        let temp = arr.map(item => {
            return {
                code: item.code,
                name: item.name
            };
        });
        result = result.concat(temp);
        // 再看是否有children,如果存在,再处理下一级
        arr.forEach(item => {
            if (item.children) next(item.children);
        });
    };
    next(address);

    // 返回按照code查找的方法「去扁平化后的数组中查找」
    return function getNameByCode(code) {
        let item = result.find(item => item.code == code);
        return item ? item.name : '';
    };
})(address);
console.log(getNameByCode('130102')); //"长安区"
console.log(getNameByCode('1302')); //"唐山市"




3.对象扁平化处理

/* 把对象处理为下述扁平化的结构 */
const obj = {
    a: {
        b: 1,
        c: 2,
        d: { e: 3, 2: 200 },
    },
    b: [1, 2, { a: 3, b: 4 }],
    c: 1,
    1: 100,
    x: {}
};

Object.defineProperty(Object, 'flatten', {
    enumerable: false,
    writable: true,
    configurable: true,
    value: function flatten(obj) {
        let result = {};
        const next = (obj, attr) => {
            let isObject = _.isPlainObject(obj),
                isArray = Array.isArray(obj);
            if (isArray || isObject) {
                // 考虑为空的情况
                if (isObject && _.isEmptyObject(obj)) {
                    result[attr] = {};
                    return;
                }
                if (isArray && obj.length === 0) {
                    result[attr] = [];
                    return;
                }
                // 不为空的情况则迭代处理
                _.each(obj, (value, key) => {
                    let temp = isNaN(key) ? `.${key}` : `[${key}]`;
                    next(value, attr ? attr + temp : key);
                });
                return;
            }
            result[attr] = obj;
        };
        next(obj, "");
        return result;
    }
});
console.log(Object.flatten(obj));


/* 
// 输出结果:
let objFlatten = {
    1: 100,
    'a.b': 1,
    'a.c': 2,
    'a.d.e': 3,
    'a.d[2]': 200,
    'b[0]': 1,
    'b[1]': 2,
    'b[2].a': 3,
    'b[2].b': 4,
    'c': 1,
    x: {}
}; 
*/

4.对象扁平化处理

let obj = {
    a: {
        b: {
            c: {
                d: 1
            }
        }
    }
};

const getValue = (obj, keyPath) => {
    let keys = keyPath.split('.'),
        index = 0,
        result;
    const next = x => {
        if (index >= keys.length) return;
        let key = keys[index++];
        result = x[key];
        if (result == null || typeof result !== "object") return;
        next(result);
    };
    next(obj);
    return result;
};

/* const getValue = (obj, keyPath) => {
    let keys = keyPath.split('.');
    return keys.reduce((x, key) => {
        return x ? x[key] : undefined;
    }, obj);
}; */
console.log(getValue(obj, 'a.b.c.d')); //1
console.log(getValue(obj, 'a.b')); //{c:{d:1}}
console.log(getValue(obj, 'a.b.x.y')); //undefined

/* 可选链处理 */
/* const getValue = (objName, keyPath) => {
    keyPath = keyPath.replace(/\./g, '?.');
    return eval(`${objName}?.${keyPath}`);
};
console.log(getValue('obj', 'a.b.c.d')); //1
console.log(getValue('obj', 'a.b')); //{c:{d:1}} */

5.一堆数组转树结构(一维转多维)

let data = [
    { id: 0, parentId: null, text: '北京市' },
    { id: 1, parentId: 0, text: '昌平区' },
    { id: 2, parentId: 1, text: '海淀区' },
    { id: 3, parentId: null, text: '河北省' },
    { id: 4, parentId: null, text: '山西省' },
    { id: 5, parentId: 3, text: '承德市' },
    { id: 6, parentId: 3, text: '石家庄市' }
];

/* 方案一 O(N^2) */

const list2Tree = function list2Tree(data) {
    // 先找出第一级列表
    let arr = data.filter(item => item.parentId === null);
    // 迭代第一级的数据,筛选出其子集数据
    arr.forEach(item => {
        let children = data.filter(cur => cur.parentId == item.id);
        if (children.length > 0) item.children = children;
    });
    return arr;
};
console.log(list2Tree(data)); 

/* 方案二:利用map数据结构处理 O(N)*/
const list2Tree = function list2Tree(data) {
    // 把data变为Map数据结构
    let map = new Map(),
        result = [];
    data.forEach(item => {
        map.set(item.id, item);
    });
    // 迭代数组中的每一项,根据parentId做不同的处理
    data.forEach(item => {
        let { parentId } = item,
            parent;
        // parentId是null的,说明其就是第一级,我们把其加入到result中即可
        if (parentId === null) {
            result.push(item);
            return;
        }
        // parentId不是null的,说明其实第二级,我们根据parentId找到其所属的第一级,把当前迭代这一项作为其children加入进去
        parent = map.get(parentId);
        parent.children ? parent.children.push(item) : parent.children = [item];
    });
    return result;
};
console.log(list2Tree(data));

6.数据组合问题

const obj = {
    data: [
        ['xiaoming', 'male', '18', 'beijing', '2020-01-02'],
        ['xiaofang', 'female', '18', 'shanghai', '2020-03-02']
    ],
    columns: [
        { name: 'name', note: '' },
        { name: 'gender', note: '' },
        { name: 'age', note: '' },
        { name: 'address', note: '' },
        { name: 'registerTime', note: '' },
    ]
};
输出下面结果 
[
    { name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' },
    { name: 'xiaofang', 'gender': 'female', age: '18', address: 'shanghai', registerTime: '2020-03-02' }
]

方案一:
 const combine = function combine(obj) {
    let { data, columns } = obj,
        columnsKeys = {};
    // 先把columns变为 {name:0,gender:1,...} 这种格式
    columns.forEach((item, index) => {
        columnsKeys[item.name] = index;
    });
    // 外层迭代数据DATA
    return data.map(item => {
        // item: ['xiaoming', 'male', '18', 'beijing', '2020-01-02']
        // columnsKeys: {name: 0, gender: 1, age: 2, address: 3, registerTime: 4}
        // 想要的结果 { name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' }
        let obj = {};
        _.each(columnsKeys, (index, key) => {
            obj[key] = item[index];
        });
        return obj;
    });
}; 

方案二:
const combine = function combine(obj) {
    let { data, columns } = obj;
    // 把columns按照每列的字段名扁平化
    columns = columns.map(item => item.name);
    // console.log(columns); //['name', 'gender', 'age', 'address', 'registerTime']
    return data.map(item => {
        // item: ['xiaoming', 'male', '18', 'beijing', '2020-01-02']
        // 想要的结果 { name: 'xiaoming', 'gender': 'male', age: '18', address: 'beijing', registerTime: '2020-01-02' }
        let obj = {};
        columns.forEach((key, index) => {
            obj[key] = item[index];
        });
        return obj;
    });
};

用qs .stringify方法转换

npm i qs 

/*

const obj = {

    a: {

        b: 1,

        c: 2,

        d: { e: 3, 2: 200 },

    },

    b: [1, 2, { a: 3, b: 4 }],

    c: 1,

    1: 100,

    x: {}

};

// 转换为JSON字符串

// console.log(JSON.stringify(obj));

// 转换为URLENCODED格式字符串「有的后台要求AJAX请求主体传递这样的格式」

// console.log(Qs.stringify(obj)); //'1=100&a[b]=1&a[c]=2&a[d][2]=200&a[d][e]=3&b[0]=1&b[1]=2&b[2][a]=3&b[2][b]=4&c=1'

*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值