Một lớp lót đơn giản. WARNING. Điều này làm biến đối tượng đã được chọn thay thế vì trả lại một đối tượng mới
let o = Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
Giống như trên nhưng được viết là một chức năng
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
Hàm này sử dụng đệ quy để loại bỏ các mục khỏi các đối tượng lồng nhau
function removeEmpty[obj] {
return Object.fromEntries[
Object.entries[obj]
.filter[[[_, v]] => v != null]
.map[[[k, v]] => [k, v === Object[v] ? removeEmpty[v] : v]]
];
}
Ví dụ về ES6/ES2015
Một lớp lót đơn giản. WARNING. Điều này làm biến đối tượng đã được chọn thay thế vì trả lại một đối tượng mới
Object.keys[obj].forEach[[k] => obj[k] == null && delete obj[k]];
Một tuyên bố duy nhất [không thay đổi các đối tượng đã cho]
let o = Object.keys[obj]
.filter[[k] => obj[k] != null]
.reduce[[a, k] => [{ ...a, [k]: obj[k] }], {}];
Giống như trên nhưng được viết là một chức năng
Hàm này sử dụng đệ quy để loại bỏ các mục khỏi các đối tượng lồng nhauHàm này sử dụng đệ quy để loại bỏ các mục khỏi các đối tượng lồng nhau
function removeEmpty[obj] {
return Object.entries[obj]
.filter[[[_, v]] => v != null]
.reduce[
[acc, [k, v]] => [{ ...acc, [k]: v === Object[v] ? removeEmpty[v] : v }],
{}
];
}
Ví dụ về ES6/ES2015
function removeEmpty[obj] {
const newObj = {};
Object.entries[obj].forEach[[[k, v]] => {
if [v === Object[v]] {
newObj[k] = removeEmpty[v];
} else if [v != null] {
newObj[k] = obj[k];
}
}];
return newObj;
}
Một lớp lót đơn giản. WARNING. Điều này làm biến đối tượng đã được chọn thay thế vì trả lại một đối tượng mới
Một tuyên bố duy nhất [không thay đổi các đối tượng đã cho]
function removeEmpty[obj] {
return Object.entries[obj]
.filter[[[_, v]] => v != null]
.reduce[[acc, [k, v]] => [{ ...acc, [k]: v }], {}];
}
function removeEmpty[obj] {
return Object.keys[obj]
.filter[function [k] {
return obj[k] != null;
}]
.reduce[function [acc, k] {
acc[k] = obj[k];
return acc;
}, {}];
}
Giống như chức năng trên, nhưng được viết theo cách bắt buộc [không chức năng]
function removeEmpty[obj] {
const newObj = {};
Object.keys[obj].forEach[function [k] {
if [obj[k] && typeof obj[k] === "object"] {
newObj[k] = removeEmpty[obj[k]];
} else if [obj[k] != null] {
newObj[k] = obj[k];
}
}];
return newObj;
}
Ví dụ về ES5/ES2009
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
0Delete the null value from a object #
Để xóa tất cả các giá trị null khỏi một đối tượng. use object. Phương thức khóa [] để có được một dãy phím của đối tượng. Use method foreach[] to set over the keys. Kiểm tra xem từng giá trị có bằng null và xóa các giá trị null bằng toán tử không xóa
Phải nói rằng 3 hàm đồ, lọc và giảm giúp ích rất nhiều. Nếu như các bạn nếu còn đang mơ hồ về chúng thì nên dành thời gian để tìm hiểu, còn tôi sẽ tóm tắt lại một chút về công dụng của 3 hàm này
chức năng bản đồ
Một hàm
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
16 hoạt động đối với kiểu dữ liệu là mảng, nó nhận tham số đầu vào là một hàm và trả về kết quả là một mảng với độ dài các phần tử luôn bằng gốc dữ liệu. Về cơ bản, chúng ta sử dụng bản đồ khi có mong muốn lặp lại các phần tử trong mảng để bổ sung/sửa/xoá… dữ liệu của chúngHàm gọi lại của hàm map có các tham số
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
17, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
18, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
19 tương ứng với phần từ hiện tại, vị trí và dữ liệu của mảngfunction removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
5function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
6Map function là một khai phá của Functor, nếu chưa biết về functor bạn có thể đọc bài viết của tôi tại Functor là gì?
Ví dụ một mảng người dùng có các thông tin cơ bản như sau
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
1function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
8Tăng tuổi của mỗi người thêm 1
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
9function removeEmpty[obj] {
return Object.fromEntries[
Object.entries[obj]
.filter[[[_, v]] => v != null]
.map[[[k, v]] => [k, v === Object[v] ? removeEmpty[v] : v]]
];
}
0Ghi chú. Trường hợp này tôi đang cố ý tạo ra một đối tượng mới và trả về để tránh tham chiếu, sau khi chạy xong thì tôi có một mảng users2 hoàn toàn không tham chiếu đến người dùng
Tôi thấy có một số người yêu thích cách viết
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
5function removeEmpty[obj] {
return Object.fromEntries[
Object.entries[obj]
.filter[[[_, v]] => v != null]
.map[[[k, v]] => [k, v === Object[v] ? removeEmpty[v] : v]]
];
}
2Ngắn gọn hơn rất nhiều nhưng vì thế vô tình đã làm thay đổi dữ liệu của người dùng, có thể gây ra các vấn đề về dữ liệu nếu không quản lý được việc sử dụng của người dùng ở những nơi khác. Vì vậy nếu có thể thì nên giới hạn cách viết này, thay vào đó hãy tạo ra một mảng mới
chức năng lọc
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
80 được sử dụng để lọc ra các phần tử điều kiện đối xứng trong mảng. Đầu ra của bộ lọc luôn là một mảng có độ dài nhỏ hơn hoặc bằng dữ liệu gốc. Hàm callback của filter cũng giống map, nó chứa các tham số
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
17, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
18, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
19. Ví dụ tôi muốn lọc ra danh sách người dùng có tuổi >= 20
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
5function removeEmpty[obj] {
return Object.fromEntries[
Object.entries[obj]
.filter[[[_, v]] => v != null]
.map[[[k, v]] => [k, v === Object[v] ? removeEmpty[v] : v]]
];
}
8Bộ lọc sẽ dựa trên kết quả của lệnh gọi lại hàm trả về là đúng hoặc sai để lọc dữ liệu, nếu đúng là lấy còn sai thì không.
Vì bộ lọc chỉ có thể lọc ra phần tử được lấy từ mảng gốc nên dữ liệu mới được tạo ra từ bộ lọc sẽ có tham chiếu đến dữ liệu gốc nên cần thận trọng.
giảm chức năng
Không giống với bản đồ và bộ lọc, đầu ra của giảm không được đảm bảo. Nó có thể là bất kỳ loại dữ liệu nào tùy thuộc vào mục đích.
Reduce sẽ duyệt qua từng phần tử trong mảng, thực thi một hàm tính toán rồi trả về dữ liệu duy nhất.
Hàm gọi lại của reduce có 4 giá trị
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
84, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
85, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
18, function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
19 lần lượt là tham số nhận vào ban đầu, phần tử hiện tại, vị trí phần tử hiện tại và mảng ban đầu. function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
5function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
61Lý thuyết thì là dài dòng nhưng tôi sẽ lấy một ví dụ đơn giản trước tiên, dưới đây là ví dụ sử dụng giảm để tính tổng các số có trong mảng
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
62function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
630 là giá trị ban đầu vào lệnh cấm tương ứng với
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
84, sau đó cứ sau mỗi lần lặp nó thực hiện phép tính function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
84 + function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
85, kết quả thì gán ngược lại cho function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
84. Nên function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
84 là giá trị tích lũy sau mỗi lần lặp và nó cũng là kết quả cuối cùng giảm sẽ được trả raMột ví dụ phức tạp hơn, tôi sẽ không sử dụng bộ lọc để lọc ra danh sách người dùng có tuổi >= 20, thay vào đó sẽ sử dụng giảm
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
64____165Với cách này, tôi có thể tránh được tham chiếu như khi sử dụng bộ lọc mặc dù nó hơi dài dòng
Hai level when used function callback
Ở trong các ví dụ tôi đều viết hàm gọi lại trực tiếp vào các chức năng, điều đó giúp tôi viết mã nhanh hơn nhưng đổi lại bạn sẽ có những đoạn mã dài dòng đôi khi còn gây khó khăn cho người đọc .
Tôi tạm gọi cách viết như trên là cấp độ 1. Vì thế ở cấp 2 bạn sẽ viết như thế nào?
Đó là cách viết bằng hàm cà ri, nếu bạn chưa biết về cà ri thì có thể tham khảo bài viết và hàm cà ri là gì? .
Ví dụ tôi giải quyết yêu cầu ban đầu là tăng tuổi của mỗi người dùng lên 1
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
66function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
67Tôi tạo một hàm
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
93 có nhiệm vụ là nhận một đối tượng, tăng giá trị thuộc tính tuổi lên 1 rồi trả lại một đối tượng hoàn toàn mới. Sau đó, bản đồ nhận nó như một cuộc gọi lại để xử lý dữ liệu. Nhìn vào dòng 2, bạn có thể thấy đoạn mã tập trung vào nó đang làm gì hơn là nó đang làm như thế này…Cho đến bây giờ thì các yêu cầu chỉnh sửa dữ liệu hay lọc dữ liệu đơn giản mà tôi đưa ra đều được giải quyết mặc dù hơi khó thời gian viết mã một chút. Do đó, hãy đến với một yêu cầu phức tạp hơn. Tôi muốn nhóm người dùng theo city_code và sắp xếp người dùng theo thứ tự giảm dần của tuổi?
Tôi sẽ không phát triển mã khai thác theo yêu cầu này vì mã có thể sẽ khá dài, thay vào đó tôi đưa ra cách làm như sau. Đầu tiên lấy tất cả các giá trị city_code ra rồi bộ lọc dữ liệu [duy nhất], lặp lại từng giá trị city_code để tìm những người dùng còn sót lại. End the end of the each group to sort the thứ tự người dùng trong mỗi nhóm.
Đó là cách của tôi nghĩ ra được, nếu bạn còn cách nào khác thì hãy comment cho mọi người cùng biết nhé.
Vì vậy, có cách nào rút gọn để giải quyết vấn đề mà không cần nhiều mã không? . Please use lodash
Sử dụng lodash để tăng tốc độ cài đặt
Cho những ai chưa biết thì lodash là một thư viện lý liệu dữ liệu rất nổi tiếng, với hơn 50k sao trên github thì các bạn cũng đủ biết mức độ phổ biến của thư viện này như thế nào rồi nhé.
Go lodash thì nó là tập hợp các hàm tiện ích trong việc xử lý dữ liệu như Array hay Object, thậm chí chí là cả kiểu dữ liệu String, Number…. Nó rất là nhiều hàm, bạn có thể xem trên trang Tài liệu.
Trong lodash có hàm
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
94 để phân nhóm và hàm function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
95 để sắp xếp dữ liệu, áp dụng nó vào giải quyết yêu cầu nhóm theo city_code trên của tôifunction removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
66function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
69Kết quả sẽ trông giống như
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
10function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
11Đừng quên chúng ta vẫn còn một yêu cầu nữa là sắp xếp lại dữ liệu trong mỗi nhóm theo tuổi giảm dần.
Trong lodash có một hàm là
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
96 có thể giúp tôi sắp xếp dữ liệu theo thứ tự tăng hoặc giảm. function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
12function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
13function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
97 là hàm cho phép sửa đổi giá trị của từng thuộc tính có trong đối tượng. Ở đây tôi sử dụng function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
97 để sắp xếp dữ liệu trong mỗi nhómLodash còn hỗ trợ cách viết chuỗi hàm, nghĩa là một chuỗi các hàm nối liền nhau. Đầu ra của hàm này sẽ là đầu vào của hàm kia. Có thể nói nó giống như hàm soạn thảo/ống dẫn mà tôi đã có bài viết ở Triển khai mã hiệu quả hơn so với hàm soạn thảo & ống dẫn trong Javascript
function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
9function removeEmpty[obj] {
return Object.fromEntries[Object.entries[obj].filter[[[_, v]] => v != null]];
}
15Hai cách đều giải quyết được vấn đề, tuy nhiên cách 1 thì tập trung vào làm như thế nào còn cách 2 thì đang làm gì hơn