我有以下陣列
var array = [
{
group: "FL",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
},
{
group: "QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
}
]
我需要檢查串列陣列,如果串列陣列中的所有物件都完全相同,那么我需要將其合并如下:
[
{
group: "FL,QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
}
]
我通過使用reduce方法回圈陣列和其他兩個函式來比較物件來嘗試這個,但不知何故它不起作用
array.reduce(async(acc, item) => {
const exist = await compareObjects(acc, item);
if (exist) {
acc[exist.index].group= exist.group ',' item.group;
} else {
acc.push(item)
}
return acc;
}, [])
async function compareObjects(o1, o2) {
for (let i = 0; i < o1.length; i ) {
const value = await checkObjs(o1[i].list, o2.list);
if(value) { return {index:i , group: o1[i].group} }
}
}
function checkObjs(arr1, arr2) {
return arr1.length === arr2.length && arr1.every((el, i) => objectsEqual(el, arr2[i]))
}
const objectsEqual = (o1, o2) =>
Object.keys(o1).length === Object.keys(o2).length
&& Object.keys(o1).every(p => o1[p] === o2[p]);
任何幫助,將不勝感激 。謝謝
uj5u.com熱心網友回復:
您可以使用它Array.reduce()來創建輸入物件的映射。
我們將創建一個函式getListKey()來根據每個物件串列創建一個唯一的鍵。
一旦我們有了地圖,我們就可以使用它Object.values()來獲取陣列結果:
var array = [ { group: "FL", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] }, { group: "NZ", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "D", value: "Delhi" } ] }, { group: "QA", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] } ]
function getListKey(list) {
return list.sort(({key: a }, {key: b}) => a.localeCompare(b))
.map(({key, value}) => `${key}-${value}`).join(",");
}
const result = Object.values(array.reduce((acc, { group, list }) => {
const key = getListKey(list);
if (!acc[key]) {
acc[key] = { group, list };
} else {
acc[key].group = "," group;
}
return acc;
}, {}))
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
另一種方法是再次使用Array.reduce(),但使用 lodash _.isEqual()函式進行串列比較。這進行了深入的比較。我們會使用它Array.find()來獲取任何重復的串列。
var array = [ { group: "FL", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] }, { group: "NZ", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "D", value: "Delhi" } ] }, { group: "QA", list: [ { key: "A", value: "Alaska" }, { key: "B", value: "Brazil" }, { key: "C", value: "California" } ] } ]
const result = array.reduce((acc, cur) => {
const foundItem = acc.find(item => _.isEqual(item.list, cur.list));
if (foundItem) {
foundItem.group = `,${cur.group}`;
} else {
acc.push(cur);
}
return acc;
}, [])
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" referrerpolicy="no-referrer"></script>
uj5u.com熱心網友回復:
您的使用async是讓您在這里絆倒的原因,我不確定您使用它的原因。
為了使您的代碼按原樣作業,您需要await在每次迭代時使用累加器,并將結果分配reduce()給某些東西。
var array = [ { group: 'FL', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'C', value: 'California' }, ], }, { group: 'NZ', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'D', value: 'Delhi' }, ], }, { group: 'QA', list: [ { key: 'A', value: 'Alaska' }, { key: 'B', value: 'Brazil' }, { key: 'C', value: 'California' }, ], }, ];
function checkObjs(arr1, arr2) {
const objectsEqual = (o1, o2) =>
Object.keys(o1).length === Object.keys(o2).length && Object.keys(o1).every((p) => o1[p] === o2[p]);
return arr1.length === arr2.length && arr1.every((el, i) => objectsEqual(el, arr2[i]));
}
async function compareObjects(o1, o2) {
for (let i = 0; i < o1.length; i ) {
const value = await checkObjs(o1[i].list, o2.list);
if (value) {
return { index: i, group: o1[i].group };
}
}
}
// assign the result of reduce to a variable
const result = array.reduce(async (acc, item) => {
acc = await acc; // await the returned accumulator Promise
const exist = await compareObjects(acc, item);
if (exist) {
acc[exist.index].group = exist.group ',' item.group;
} else {
acc.push(item);
}
return acc;
}, []);
result.then((r) => console.log(r));
.as-console-wrapper { max-height: 100% !important; top: 0; }
uj5u.com熱心網友回復:
我認為我建議解決這個問題的方法是將其分解并(希望)使用庫函式來解決一些更復雜的問題。例如lodash你可以說
import isEqual from "lodash/isEqual";
const arr = [
{
group: "FL",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
},
{
group: "NZ",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "D", value: "Delhi" }
]
},
{
group: "QA",
list: [
{ key: "A", value: "Alaska" },
{ key: "B", value: "Brazil" },
{ key: "C", value: "California" }
]
}
];
function groupBy<T, R>(
a: T[],
iteritem: (t: T) => R,
compare: (a: R, b: R) => boolean = isEqual
) {
const groups: T[][] = [];
const rs = a.map(iteritem);
for (let i = 0; i < rs.length; i ) {
let added = false;
const r = rs[i];
for (let j = 0; j < groups.length; j ) {
if (compare(r, iteritem(groups[j][0]))) {
groups[j].push(a[i]);
added = true;
break;
}
}
if (!added) {
groups.push([a[i]]);
}
}
return groups;
}
const grouped = groupBy(arr, (a) => a.list);
const combined = [];
for (const g of grouped) {
combined.push({
group: g.map(({ group }) => group).join(","),
list: g[0].list
});
}
console.log(JSON.stringify(combined, undefined, 2));
這不是一次性的答案,因為groupBy可以重復使用。我最初想使用groupByfromlodash但它不接受自定義相等函式。
uj5u.com熱心網友回復:
這是一種可能的解決方案:
const sorted = [];
for (let i = 0; i < groups.length; i ) {
const identicalLists = [];
for (let j = i; j < groups.length; j ) {
const isIdentical =
JSON.stringify(groups[i].list) === JSON.stringify(groups[j].list);
const found = !!sorted.flat().find((item) => item === groups[j].group);
if (isIdentical && !found) {
identicalLists.push(groups[j].group);
}
}
if (identicalLists.length > 0) {
sorted.push(identicalLists);
}
}
const answer = sorted.map((item) => {
const first = groups.find((group) => group.group === item[0]);
return { group: item, list: first.list };
});
uj5u.com熱心網友回復:
減少不適用于async/await. 如果您沒有async代碼 - 從 API 獲取某些內容或使用來自 Promise 的資料的代碼,您應該洗掉async/await,因為它是同步的。
如果您的代碼使用了一些異步 API - 嘗試使用類似的東西:
export const reduceAsync = async (array, transformer, initialvalue) => {
let accumolator = typeof initialValue !== 'undefined' ? initialValue : array[0];
for (let i = 0; i < array.length; i ) {
accumolator = await transformer(accumolator, array[i], i, array);
}
return accumolator;
};
上面的函式是可重用的,并遵循此處定義的規范:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/315163.html
標籤:javascript 节点.js 打字稿
