我需要在Date
字段上对三个不同的对象数组进行排序,其中该字段在每个组中都有不同的名称。
下面是我的数据示例:
const documents = [
{
documentId: 'ADB0125A',
fileName: 'test_2018.pdf',
date': '2017-12-02T19:08:52+01:00' // Field to sort by
},
{
documentId: '123456',
fileName: 'test2_2018.pdf',
date': '2017-12-12T22:08:52+01:00' // Field to sort by
},
{
documentId: '121212',
fileName: 'test3_2018.pdf',
date': '2018-05-22T23:08:52+01:00' // Field to sort by
}];
const conversations = [
{
conversationId: '1102',
lastUpdate: '2015-10-10T18:19:12+01:00' // Field to sort by
},
{
conversationId: '5622',
lastUpdate: '2019-08-16T18:19:12+01:00' // Field to sort by
},
{
conversationId: '112',
lastUpdate: '2015-10-26T18:19:12+01:00' // Field to sort by
}];
const invoices = [
{
invoiceId: "20100392077",
rechnungsDatum: "2019-02-10" // Field to sort by
},
{
invoiceId: "5550392077",
rechnungsDatum: "2018-02-05" // Field to sort by
},
{
invoiceId: "3336392077",
rechnungsDatum: "2018-12-11" // Field to sort by
}];
目标:返回最后4个结果(一旦我列出了.reverse()
的最终集合,我就可以用ASC
获得结果),与它们来自哪个来源无关。我希望得到:
const result = [
{
conversationId: '5622',
lastUpdate: '2019-08-16T18:19:12+01:00'
},
{
invoiceId: "20100392077",
rechnungsDatum: "2019-02-10"
},
{
invoiceId: "3336392077",
rechnungsDatum: "2018-12-11"
},
{
documentId: '121212',
fileName: 'test3_2018.pdf',
date': '2018-05-22T23:08:52+01:00'
}
]
是否可以对所有三个对象使用唯一的Array.sort
方法,或者唯一的方法是成对比较它们并根据部分结果构建结果?
答案 0 :(得分:4)
您可以使用一个对象,该对象具有通缉日期属性的replacemnt键和一个平面数组,该数组保留了源和归一化日期属性,对数组进行排序并返回顶部的四个元素。
最后,删除不必要的信息并检索原始对象结构。
const
documents = [{ documentId: 'ADB0125A', fileName: 'test_2018.pdf', date: '2017-12-02T19:08:52+01:00' }, { documentId: '123456', fileName: 'test2_2018.pdf', date: '2017-12-12T22:08:52+01:00' }, { documentId: '121212', fileName: 'test3_2018.pdf', date: '2018-05-22T23:08:52+01:00' }],
conversations = [{ conversationId: '1102', lastUpdate: '2015-10-10T18:19:12+01:00' }, { conversationId: '5622', lastUpdate: '2019-08-16T18:19:12+01:00' }, { conversationId: '112', lastUpdate: '2015-10-26T18:19:12+01:00' }],
invoices = [{ invoiceId: "20100392077", rechnungsDatum: "2019-02-10" }, { invoiceId: "5550392077", rechnungsDatum: "2018-02-05" }, { invoiceId: "3336392077", rechnungsDatum: "2018-12-11" }]
keys = { documents: 'date', conversations: 'lastUpdate', invoices: 'rechnungsDatum' },
result = Object
.entries({ documents, conversations, invoices })
.reduce((r, [k, v]) => [...r, ...v.map(payload => ({ payload, date: payload[keys[k]] }))], [])
.sort((a, b) => b.date.localeCompare(a.date))
.slice(0, 4)
.map(({ payload }) => payload);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:1)
您可以按照以下步骤进行操作:
map()
添加另一个名为key
的属性,其值将是需要对该对象进行排序的值。flat()
制作一维数组sort()
,然后再应用sort()
。
const documents = [ { documentId: 'ADB0125A', fileName: 'test_2018.pdf', date: '2017-12-02T19:08:52+01:00' }, { documentId: '123456', fileName: 'test2_2018.pdf', date: '2017-12-12T22:08:52+01:00' }, { documentId: '121212', fileName: 'test3_2018.pdf', date: '2018-05-22T23:08:52+01:00' }]; const conversations = [ { conversationId: '1102', lastUpdate: '2015-10-10T18:19:12+01:00' }, { conversationId: '5622', lastUpdate: '2019-08-16T18:19:12+01:00' }, { conversationId: '112', lastUpdate: '2015-10-26T18:19:12+01:00' }]; const invoices = [ { invoiceId: "20100392077", rechnungsDatum: "2019-02-10" }, { invoiceId: "5550392077", rechnungsDatum: "2018-02-05" }, { invoiceId: "3336392077", rechnungsDatum: "2018-12-11" }];
let keys = ['date','lastUpdate','rechnungsDatum'];
const res = [documents,conversations,invoices]
.map((x,i) => x.map(a => (
{...a,key:a[keys[i]]}))
).flat()
.sort((a,b) => a.key.localeCompare(b.key))
.slice(-4)
.reverse()
.map(({key,...rest}) => rest)
console.log(res)
答案 2 :(得分:1)
您可以使用 WeakMap 存储对应该对数组进行排序的对象属性的引用,并使用存储的属性简单地查找值。
const flatten = (flat, arr) => [...flat, ...arr];
const PropMap = (props, arrs) => {
let map = new WeakMap();
for (let i=-1, arr; arr = arrs [++i];)
for (let j=0, obj; obj = arr [j++];)
map.set (obj, props [i])
return map;
}
PropMap.SortBy = map => (a,b) => {
let [l, r] = [a,b].map (obj => obj [map.get (obj)])
return l>r?-1:l<r?1:0
}
const data = [documents, conversations, invoices];
const props = ["date", "lastUpdate", "rechnungsDatum"]
const map = PropMap (props,data);
console.log (
data.reduce (flatten, []).sort (PropMap.SortBy (map)).slice (0,4)
)
<script>
const
documents = [{ documentId: 'ADB0125A', fileName: 'test_2018.pdf', date: '2017-12-02T19:08:52+01:00' }, { documentId: '123456', fileName: 'test2_2018.pdf', date: '2017-12-12T22:08:52+01:00' }, { documentId: '121212', fileName: 'test3_2018.pdf', date: '2018-05-22T23:08:52+01:00' }],
conversations = [{ conversationId: '1102', lastUpdate: '2015-10-10T18:19:12+01:00' }, { conversationId: '5622', lastUpdate: '2019-08-16T18:19:12+01:00' }, { conversationId: '112', lastUpdate: '2015-10-26T18:19:12+01:00' }],
invoices = [{ invoiceId: "20100392077", rechnungsDatum: "2019-02-10" }, { invoiceId: "5550392077", rechnungsDatum: "2018-02-05" }, { invoiceId: "3336392077", rechnungsDatum: "2018-12-11" }]
</script>
答案 3 :(得分:1)
这是我认为可以提高可读性的另一种方法:
const by = (name) => (data) => data.map(d => [d[name], d])
const topFourNewest = (...types) => types
.reduce ( (a, b) => a.concat(b) )
.sort ( (a, b, aa = a[0], bb = b[0]) => aa < bb ? 1 : aa > bb ? -1 : 0 )
.map ( ([name, value]) => value )
.slice (0, 4)
const documents = [{documentId:"ADB0125A",fileName:"test_2018.pdf",date:"2017-12-02T19:08:52+01:00"},{documentId:"123456",fileName:"test2_2018.pdf",date:"2017-12-12T22:08:52+01:00"},{documentId:"121212",fileName:"test3_2018.pdf",date:"2018-05-22T23:08:52+01:00"}]
const conversations = [{conversationId:"1102",lastUpdate:"2015-10-10T18:19:12+01:00"},{conversationId:"5622",lastUpdate:"2019-08-16T18:19:12+01:00"},{conversationId:"112",lastUpdate:"2015-10-26T18:19:12+01:00"}]
const invoices=[{invoiceId:"20100392077",rechnungsDatum:"2019-02-10"},{invoiceId:"5550392077",rechnungsDatum:"2018-02-05"},{invoiceId:"3336392077",rechnungsDatum:"2018-12-11"}]
console .log (
topFourNewest (
by ('date') (documents),
by ('lastUpdate') (conversations),
by ('rechnungsDatum') (invoices)
)
)
我们的小辅助函数by
将一个数组的每个值包装在一个由两个元素组成的数组中,键字段位于第一个,整个对象位于第二个。 (同样好的选择是将它们包装在{key, value}
对象中。)
主要功能有四个步骤:reduce
将by
中生成的这些列表合并为一个列表。 sort
显然对它们进行了排序。 (对此问题,它们按降序进行排序,但是如果我要使其更通用,我可能会进行自然排序并在单独的函数中将它们取反。这仅涉及交换-1
和{{1} }。)1
只是提取出原始对象。然后map
选择前四个元素。
我们可以想象有几种变体可以跳过helper函数,并且不会很难编写。他们可能具有以下API:
slice
或
topFourNewest (
'date', documents,
'lastUpdate', conversations,
'rechnungsDatum', invoices
)
或者,通过辅助功能(topFourNewest (
{key: 'date', data: documents},
{key: 'lastUpdate', data: conversations},
{key: 'rechnungsDatum', data: invoices}
)
),我们可以具有更大的灵活性:
const prop = (name) => (obj) => obj[name]
甚至
topFourNewest (
( prop ('date'), documents ),
( prop ('lastUpdate'), conversations ),
( prop ('rechnungsDatum'), invoices )
)
但是我喜欢这个初始版本的读取方式。
我认为有几种变体很有用。我们可以参数化数字topFourNewest (
{date: documents},
{lastUpdate: conversations},
{rechnungsDatum: invoices}
)
;我们可能想要前三名或前十名是有意义的。我们可以使用第二个函数提取要选择的值的数量,从而分离出合并和排序的方式。这些将很容易做到。
答案 4 :(得分:0)
您可以编写如下内容,
const result = [
{
conversationId: '5622',
lastUpdate: '2019-08-16T18:19:12+01:00'
},
{
invoiceId: "20100392077",
rechnungsDatum: "2019-02-10"
},
{
invoiceId: "3336392077",
rechnungsDatum: "2018-12-11"
},
{
documentId: '121212',
fileName: 'test3_2018.pdf',
date: '2018-05-22T23:08:52+01:00'
}
]
let fields = ["date","rechnungsDatum","lastUpdate"];
result.sort( (a,b)=> {
let dateA, dateB;
fields.forEach( field =>{
if(a.hasOwnProperty(field))
dateA = new Date(a[field]);
if(b.hasOwnProperty(field))
dateB = new Date(b[field]);
});
return dateA - dateB;});
console.log(result.reverse());
让我知道它是否有效。
答案 5 :(得分:0)
您可以向所有数组中的每个对象添加一个sortBy
字段。然后合并对象数组并根据自定义字段进行排序。获得前4个结果。然后删除sortBy
列:
const documents=[{documentId:'ADB0125A',fileName:'test_2018.pdf',date:'2017-12-02T19:08:52+01:00'},{documentId:'123456',fileName:'test2_2018.pdf',date:'2017-12-12T22:08:52+01:00'},{documentId:'121212',fileName:'test3_2018.pdf',date:'2018-05-22T23:08:52+01:00'}],
conversations=[{conversationId:'1102',lastUpdate:'2015-10-10T18:19:12+01:00'},{conversationId:'5622',lastUpdate:'2019-08-16T18:19:12+01:00'},{conversationId:'112',lastUpdate:'2015-10-26T18:19:12+01:00'}],
invoices=[{invoiceId:"20100392077",rechnungsDatum:"2019-02-10"},{invoiceId:"5550392077",rechnungsDatum:"2018-02-05"},{invoiceId:"3336392077",rechnungsDatum:"2018-12-11"}];
const addSortBy = (arr, sortBy) => arr.map(a => ({ ...a, sortBy: new Date(a[sortBy]) })),
takeCount = 4; // number of items needed in the output
// has all objects with an extra key which field to sortby
const merged = [...addSortBy(documents, "date"),
...addSortBy(conversations, "lastUpdate"),
...addSortBy(invoices, "rechnungsDatum")]
// sort based on the date property in sortBy
const output = merged.sort((a, b) => b.sortBy - a.sortBy)
.slice(0, takeCount)
.map(({ sortBy, ...rest }) => rest); // remove the sortBy field from objects
console.log(output)