Группируйте мой объект json и получайте подсчет каждой группы
Я работаю с двумя услугами api rest. первый получит предметы из списка под названием "Основная категория", как показано ниже: -
/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title
и он вернет следующий json: -
{
"d": {
"results": [
{
"FileSystemObjectType": 0,
"Id": 15,
"ID": 15,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "A",
"Modified": "2017-03-01T12:08:35Z",
"Created": "2017-03-01T12:08:35Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "c93d9db6-efd8-4b49-9024-f8cc30c0a48e"
},
{
"FileSystemObjectType": 0,
"Id": 16,
"ID": 16,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "B",
"Modified": "2017-03-01T12:10:27Z",
"Created": "2017-03-01T12:10:27Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "a023853c-e967-4db8-8414-a7c390dcc09a"
},
и у меня есть другой список с именем Pages
, где каждая страница связана с элементом основной категории.
/test/_api/web/lists/getbytitle('pages')/items??$select=Title,MainCategory&$filter=MainCategory eq
здесь возвращается json: -
{
"d": {
"results": [
{
"Title": "Home",
"MainCategory": "A"
},
{
"Title": "ewrwe",
"MainCategory": "A"
},
{
"Title": "tgtg",
"MainCategory": "A"
},
{
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
},
{
"Title": "jk",
"MainCategory": "A"
}
]
}
}
теперь я хочу показать таблицу, которая показывает количество страниц под каждой категорией. поэтому я выполнил следующие действия, которые выполняют следующие действия: -
- получить все основные категории.
- для каждой основной категории выполните другой вызов списка страниц, чтобы получить связанные страницы и подсчитать результат.
вот мой script: -
<script>
$(document).ready(function() {
function getCurrentMainCategoryID() {
var results = "";
var html = "";
html = "<table style='margin-left:20%;width:50%;boarder:3px solid'><th style='text-align:left'>Main Category</th><th></th><th style='text-align:left'>Pages</th>";
var url = "/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title";
$.ajax({
url: url,
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
if (data.d.results.length > 0) {
results = data.d.results;
for (var j2 = 0; j2 < results.length; j2++) {
var currentMainCatTitle = results[j2].Title;
$.ajax({
url: "/test/_api/web/lists/getbytitle('pages')/items??$select=Title,MainCategory&$filter=MainCategory eq " + "'" + currentMainCatTitle + "'",
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
if (data.d.results.length > 0) {
html = html + "<tr><td>" + "</td>" + "<td> </td><td>" + data.d.results.length + "</td></tr>";
}
},
error: function(data) {
}
});
}
}
},
error: function(data) {
}
});
$("#inserthere").after(html + "</table>");
return results;
}
getCurrentMainCategoryID();
});
</script>
теперь мой script покажет правильный результат. но я столкнулся с проблемой производительности, так как я инициирую отдельный вызов для каждой основной категории.
поэтому я не уверен, могу ли я изменить свой script, чтобы сделать следующее: -
- получить все основные категории (как я это делаю сейчас).
- получить все страницы сразу. вместо того, чтобы отдельно получать страницы для каждой основной категории.
- внутри script для группировки страниц в соответствии с их основной категорией. и сохранить результаты внутри временной переменной
- перебирает элементы основной категории и для каждого элемента основной категории получает свой счет из переменной temp на шаге 3...
может ли кто-нибудь посоветовать это, пожалуйста? как я могу сгруппировать мой json на основе основной категории?
Ответы
Ответ 1
Если вы хотите сделать минимальное количество вызовов ajax, вам нужно будет сделать всего два, как вы говорите (хотя вы могли бы сделать это только с одним, если действительно, действительно хотели). Ключ состоит в их гнездовании: так что успех первого запускает второй, а затем успешный ответ второго отображает результаты.
Я сделал бы что-то вроде следующего. Здесь я просто показываю идентификатор GUID из основных категорий и количество совпадающих страниц, которое, если я правильно понимаю, по сути является тем, что вам нужно.
var mainCategorySimulatedResponse = {
"d": {
"results": [{
"FileSystemObjectType": 0,
"Id": 15,
"ID": 15,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "A",
"Modified": "2017-03-01T12:08:35Z",
"Created": "2017-03-01T12:08:35Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "c93d9db6-efd8-4b49-9024-f8cc30c0a48e"
}, {
"FileSystemObjectType": 0,
"Id": 16,
"ID": 16,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "B",
"Modified": "2017-03-01T12:10:27Z",
"Created": "2017-03-01T12:10:27Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "a023853c-e967-4db8-8414-a7c390dcc09a"
}]
}
}
var pagesSimulatedResponse = {
"d": {
"results": [{
"Title": "Home",
"MainCategory": "A"
}, {
"Title": "ewrwe",
"MainCategory": "A"
}, {
"Title": "tgtg",
"MainCategory": "A"
}, {
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
}, {
"Title": "jk",
"MainCategory": "A"
}, {
"Title": "Cliff Curtis",
"MainCategory": "B"
}, {
"Title": "Martin Henderson",
"MainCategory": "B"
}]
}
}
$(document).ready(function() {
function showMainCategoryData() {
var mainCategories, pages;
/*
// Make nested ajax calls here, one for Main Categories, the other for Pages.
$.ajax({
url: url,
...
success: function(data) {
if (data.d.results.length > 0) {
// store Main Categories data
mainCategories = data.d.results;
// call nested `Pages` ajax (only runs with Main Categories successful response)
$.ajax({
url: url,
...
success: function(data) {
if (data.d.results.length > 0) {
// store Pages data
pages = data.d.results;
// display results
displayResults();
} else {
console.log('Pages returned no data');
}
},
error: function(data) {}
});
} else {
console.log('MainCategories returned no data');
}
},
error: function(data) {}
});
*/
function displayResults() {
var results = "";
var html = "<table class='mainCatTable'><th class='mainCatHdr'>Main Category</th><th class='mainCatHdr'>Pages</th>";
//loop over Main Categories
for (var catIdx = 0; catIdx < mainCategories.length; catIdx++) {
var pageCount = 0;
for (var pageIdx in pages) {
if (pages[pageIdx].MainCategory == mainCategories[catIdx].Title)
pageCount++;
}
html += "<tr><td class='padRight'>" + mainCategories[catIdx].GUID + "</td>" + "<td>" + pageCount + "</td></tr>";
}
$("#inserthere").append(html + "</table>");
}
/*************** emulation code only ***************/
// emulate above ajax calls
function ajaxCatSuccess(data) {
if (data.d.results.length > 0) {
// store Main Categories data
mainCategories = data.d.results;
// emulate call to nested `Pages` ajax
ajaxPageSuccess(pagesSimulatedResponse);
} else {
console.log('MainCategories returned no data');
}
}
function ajaxPageSuccess(data) {
if (data.d.results.length > 0) {
// store Pages data
pages = data.d.results;
// display results
displayResults();
} else {
console.log('Pages returned no data');
}
}
// trigger first simulated ajax call
ajaxCatSuccess(mainCategorySimulatedResponse)
/************ end of emulate code ***************/
}
showMainCategoryData();
});
.mainCatTable {
margin-left: 10%;
width: 80%;
border: 3px solid
}
.mainCatHdr {
text-align: left
}
.padRight {
padding-right: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="inserthere"></div>
Ответ 2
Может быть, очистка вашего кода поможет? То, что я имел в виду, это получить все вызовы, которые вам нужно сделать в один массив, а затем арифметически отобразить вызовы api, после чего вы быстрее вернете все страницы. Вам нужно сделать параллельное отображение getPages
.
<script>
$(document).ready(function() {
function getCurrentMainCategoryID() {
var results = "";
var html = "<table style='margin-left:20%;width:50%;boarder:3px solid'><th style='text-align:left'>Main Category</th><th></th><th style='text-align:left'>Pages</th>";
var url = "/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title";
$.ajax({
url: url,
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
var getTitle = result => result.Title;
var results = data.d.results;
var titles = results.map(getTitle);
// not sure if it will be done in parallel
// look for a library async.js vs parallel.js ???
titles.map(title => getPages(title))
}
});
$("#inserthere").after(html + "</table>");
return results;
});
function getPages(title) {
$.ajax({
url: "/test/_api/web/lists/getbytitle('pages')/items??$select=Title,MainCategory&$filter=MainCategory eq " + "'" + title + "'",
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
if (data.d.results.length > 0) {
html = html + "<tr><td>" + "</td>" + "<td> </td><td>" + data.d.results.length + "</td></tr>";
}
}
});
}
getCurrentMainCategoryID();
});
</script>
если вы хотите группировать элементы в массив объектов, просто обновите второй вызов ajax, чтобы создать объект данных и на первой карте над mainCat, чтобы создать массив желаемой группировки:
$(document).ready(function() {
function getCurrentMainCategoryID() {
var grouped;
var html = "<table style='margin-left:20%;width:50%;boarder:3px solid'><th style='text-align:left'>Main Category</th><th></th><th style='text-align:left'>Pages</th>";
var url = "/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title";
$.ajax({
url: url,
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
var getTitle = result => result.Title;
var results = data.d.results;
var titles = results.map(getTitle);
grouped = titles.map(title => {
return {title: title, results: getPages(title)}
});
console.log(grouped);
}
});
$("#inserthere").after(html + "</table>");
return grouped;
});
function getPages(title) {
var resultsObject;
$.ajax({
url: "/test/_api/web/lists/getbytitle('pages')/items??$select=Title,MainCategory&$filter=MainCategory eq " + "'" + title + "'",
method: "GET",
async: false,
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
resultsObject = {
pages: data.d.results,
length: data.d.results.length
}
}
});
return resultsObject;
}
getCurrentMainCategoryID();
});
группировка образцов
[
{
title: _,
results: {
pages: [...],
length: n
}
}, {
title: _,
results: {
pages: [...],
length: n
}
},
]
Если вы получите все данные за один вызов, вы можете запросить mainCategories
и группу.
пример кода для группировки
function getMainCat(data, cat) {
let grouped = data.reduce((acc, item) => {
let selection = Object.keys(item).reduce((acc, key) => {
let results = item[key].results;
let pages = results.filter(result => result["MainCategory"] == cat);
let select = {
title: key,
results: {
pages: pages,
length: pages.length
}
}
return acc.concat(select);
}, []);
return acc.concat(selection);
}, []);
return grouped;
}
let data = [
{
"d": {
"results": [
{
"Title": "Home",
"MainCategory": "A"
}, {
"Title": "ewrwe",
"MainCategory": "A"
}, {
"Title": "tgtg",
"MainCategory": "A"
}, {
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
}, {
"Title": "jk",
"MainCategory": "B"
}
]
}
}
]
console.log("searching A: ");
console.log(getMainCat(data, 'A'));
console.log("searching B: ");
console.log(getMainCat(data, 'B'));
console.log("searching C: ");
console.log(getMainCat(data, 'C'));
Ответ 3
Некоторые предложения:
- Вместо вызова вызова
Pages
API каждый раз, основываясь на ответе на вызов mainCategory
API. Вы можете вызывать оба API (mainCategory и pages) только один раз, чтобы повысить производительность приложения.
-
Вы можете вызвать оба API асинхронно, чтобы получить данные на загрузке страницы.
$(document).ready(function() {
function getCurrentMainCategoryID() {
var url = "/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title";
$.ajax({
url: url,
method: "GET",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
if (data.d.results.length > 0) {
var mainCategoriesData = data.d.results;
getPagesData();
} else {
console.log('MainCategories returned no data');
}
function getPagesData() {
var url = "/test/_api/web/lists/getbytitle('pages')/items";
$.ajax({
url: url,
method: "GET",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function(data) {
if (data.d.results.length > 0) {
var pagesData = data.d.results;
} else {
console.log('Pages returned no data');
}
}
});
}
}
});
Теперь у вас есть данные Pages
и main category
.
var mainCategoriesData = [
{
"FileSystemObjectType": 0,
"Id": 15,
"ID": 15,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "A",
"Modified": "2017-03-01T12:08:35Z",
"Created": "2017-03-01T12:08:35Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "c93d9db6-efd8-4b49-9024-f8cc30c0a48e"
},
{
"FileSystemObjectType": 0,
"Id": 16,
"ID": 16,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "B",
"Modified": "2017-03-01T12:10:27Z",
"Created": "2017-03-01T12:10:27Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "a023853c-e967-4db8-8414-a7c390dcc09a"
}];
var pagesData = [
{
"Title": "Home",
"MainCategory": "A"
},
{
"Title": "ewrwe",
"MainCategory": "A"
},
{
"Title": "tgtg",
"MainCategory": "A"
},
{
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
},
{
"Title": "jk",
"MainCategory": "A"
}
];
Используя для... в, вы можете повторить ответ и получить page counts
в соответствии с main category
.
DEMO
var mainCategoriesData = [
{
"FileSystemObjectType": 0,
"Id": 15,
"ID": 15,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "A",
"Modified": "2017-03-01T12:08:35Z",
"Created": "2017-03-01T12:08:35Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "c93d9db6-efd8-4b49-9024-f8cc30c0a48e"
},
{
"FileSystemObjectType": 0,
"Id": 16,
"ID": 16,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "B",
"Modified": "2017-03-01T12:10:27Z",
"Created": "2017-03-01T12:10:27Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "a023853c-e967-4db8-8414-a7c390dcc09a"
}];
var pagesData = [
{
"Title": "Home",
"MainCategory": "A"
},
{
"Title": "ewrwe",
"MainCategory": "A"
},
{
"Title": "dkjfkdf",
"MainCategory": "B"
},
{
"Title": "tgtg",
"MainCategory": "A"
},
{
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
},
{
"Title": "slkfjrel",
"MainCategory": "B"
},
{
"Title": "jk",
"MainCategory": "A"
}
];
var resArr = [];
var count = 1;
for (var i in mainCategoriesData) {
for (var j in pagesData) {
if(pagesData[j].MainCategory == mainCategoriesData[i].Title) {
mainCategoriesData[i].pagesCount = count++;
}
}
count = 1;
resArr.push({
"Main Category": mainCategoriesData[i].Title,
"PagesCount": mainCategoriesData[i].pagesCount
})
}
console.log(resArr);
Ответ 4
Используйте jQuery.getJSON()
, он вернет уже обработанный объект. Вам нужны только два вызова ajax. Измените URL-адрес и удалите фильтр для категории, в которой вы хотите получить все страницы за один раз.
var results = [];
var html = "<table style='margin-left:20%;width:50%;boarder:3px solid'><th style='text-align:left'>Main Category</th><th></th><th style='text-align:left'>Pages</th>";
$.getJSON( "/test/_api/web/lists/getbytitle('MainCategory')/items?$select=Title")
.done(function( categories ) {
var mainCategoryResults = categories.d.results;
$.getJSON( "/test/_api/web/lists/getbytitle('pages')/items?$select=Title,MainCategory")
.done(function( pages ) {
var pageResults = pages.d.results;
$(mainCategoryResults).each(function(k,v){
var i=0;
$(pageResults).each(function(key,val){
if(v['Title'] === val['MainCategory']){
i++;
}
});
results.push([v.Title,i]);
});
})
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ", " + error;
console.log( "Pages Request Failed: " + err );
});
})
.fail(function( jqxhr, textStatus, error ) {
var err = textStatus + ", " + error;
console.log( "Categories Request Failed: " + err );
});
Вы можете проверить цикл double each()
, который создает результат в нижеприведенном фрагменте.
var a = {
"d": {
"results": [{
"FileSystemObjectType": 0,
"Id": 15,
"ID": 15,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "A",
"Modified": "2017-03-01T12:08:35Z",
"Created": "2017-03-01T12:08:35Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "c93d9db6-efd8-4b49-9024-f8cc30c0a48e"
},
{
"FileSystemObjectType": 0,
"Id": 16,
"ID": 16,
"ContentTypeId": "0x010006DDBDD3BDC9914B92E911733F2A56E1",
"Title": "B",
"Modified": "2017-03-01T12:10:27Z",
"Created": "2017-03-01T12:10:27Z",
"AuthorId": 1,
"EditorId": 1,
"OData__UIVersionString": "1.0",
"Attachments": false,
"GUID": "a023853c-e967-4db8-8414-a7c390dcc09a"
}
]
}
};
var b = {
"d": {
"results": [{
"Title": "Home",
"MainCategory": "A"
},
{
"Title": "ewrwe",
"MainCategory": "A"
},
{
"Title": "tgtg",
"MainCategory": "A"
},
{
"Title": "dsdfsfdfsdfsdfsdfsdsdfsd",
"MainCategory": "A"
},
{
"Title": "jk",
"MainCategory": "A"
}
]
}
};
var c = [];
$(a.d.results).each(function(k, v) {
var i = 0;
$(b.d.results).each(function(key, val) {
if (v['Title'] === val['MainCategory']) {
i++;
}
});
c.push([v.Title, i]);
});
console.log(c);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>