[英]Given an array of objects, count how many (possibly different) properties are defined
在 GeoJSON 文件中,某些屬性由整個集合(數組)的所有“特征”(元素)共享。 但是某些屬性僅為集合的一個子集定義。 我發現了這個問題: [javascript] 計算對象數組中對象的屬性,但它沒有回答我的問題。
例子:
const features =
[ {"properties":{"name":"city1","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4] ...]}},
{"properties":{"name":"city2","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4] ...]}},
{"properties":{"name":"city3"},"geometry":{"type":"multiPolygon","coordinates":[[[1,2],[3,4] ...]]}},
// ... for instance 1000 different cities
{"properties":{"name":"city1000","zip":1234,"updated":"May-2018"}, "geometry":{"type":"polygon","coordinates":[...]}}
];
預期結果:列出所有現有屬性及其基數,讓我們知道數據集的(不)完整程度。 例如:
properties: 1000, properties.name: 1000, properties.zip: 890, properties.updated: 412,
geometry: 1000, geometry.type: 1000, geometry.coordinates: 1000
我有一個(相當復雜的)解決方案,但我確實懷疑有些人已經面臨同樣的問題(似乎是數據科學經典),但有一個更好的(性能很重要)。
這是我笨拙的解決方案:
// 1: list all properties encountered in the features array, at least two levels deep
const countProps = af => af.reduce((pf,f) =>
Array.from(new Set(pf.concat(Object.keys(f)))), []);
// adding all the properties of each individual feature, then removing duplicates using the array-set-array trick
const countProp2s = af => af.reduce((pf,f) =>
Array.from(new Set(pf.concat(Object.keys(f.properties)))), []);
const countProp2g = af => af.reduce((pf,f) =>
Array.from(new Set(pf.concat(Object.keys(f.geometry)))), []);
// 2: counting the number of defined occurrences of each property of the list 1
const countPerProp = (ff) => pf => ` ${pf}:${ff.reduce((p,f)=> p+(!!f[pf]), 0)}`;
const countPerProp2s = (ff) => pf => ` ${pf}:${ff.reduce((p,f)=> p+(!!f.properties[pf]), 0)}`;
const countPerProp2g = (ff) => pf => ` ${pf}:${ff.reduce((p,f)=> p+(!!f.geometry[pf]), 0)}`;
const cardinalities = countProps(features).map((kk,i) => countPerProp(ff)(kk)) +
countProp2s(features).map(kk => countPerProp2s(ff)(kk)) +
countProp2g(features).map(kk => countPerProp2g(ff)(kk));
因此,存在三個問題:
- 步驟 1:對於一個相當簡單的操作,這是很多工作(在刪除大部分之前添加所有內容)。 此外,這不是遞歸的,第二級是“手動強制”。
-第 2 步,遞歸解決方案可能是更好的解決方案。
- 可以在一個步驟中執行第 1 步和第 2 步(添加新屬性時開始計數)?
我歡迎任何想法。
JSON.parse
reviver和JSON.stringify
器可用於檢查所有鍵值對:
var counts = {}, json = `[{"properties":{"name":"city1","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4]]}},{"properties":{"name":"city2","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4]]}},{"properties":{"name":"city3"},"geometry":{"type":"multiPolygon","coordinates":[[[1,2],[3,4]]]}},{"properties":{"name":"city1000","zip":1234,"updated":"May-2018"}, "geometry":{"type":"polygon","coordinates":[]}} ]` var features = JSON.parse(json, (k, v) => (isNaN(k) && (counts[k] = counts[k] + 1 || 1), v)) console.log( counts, features )
考慮嘗試以下方法。 它只是一個reduce,里面有幾個嵌套的forEach。 它檢查要返回的對象中是否存在指示計數的鍵,如果不存在則創建它們並初始化為 0。然后無論這些鍵是否存在,它們對應的值都會增加 1。
Repl 在這里: https : //repl.it/@dexygen/countobjpropoccur2levels ,代碼如下:
const features =
[ {"properties":{"name":"city1","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4]]}},
{"properties":{"name":"city2","zip":1234}, "geometry":{"type":"polygon","coordinates":[[1,2],[3,4]]}},
{"properties":{"name":"city3"},"geometry":{"type":"multiPolygon","coordinates":[[[1,2],[3,4]]]}},
{"properties":{"name":"city1000","zip":1234,"updated":"May-2018"}, "geometry":{"type":"polygon","coordinates":[]}}
];
const featuresCount = features.reduce((count, feature) => {
Object.keys(feature).forEach(key => {
count[key] = count[key] || 0;
count[key] += 1;
Object.keys(feature[key]).forEach(key2 => {
let count2key = `${key}.${key2}`;
count[count2key] = count[count2key] || 0;
count[count2key] += 1;
});
});
return count;
}, {});
console.log(featuresCount);
/*
{ properties: 4,
'properties.name': 4,
'properties.zip': 3,
geometry: 4,
'geometry.type': 4,
'geometry.coordinates': 4,
'properties.updated': 1 }
*/
使用 jackson 對 json 進行多態序列化。 它看起來像下面這樣。 您的基本界面將具有所有通用屬性,並為每個變體創建子類型。 指望每種類型都能滿足您的需求
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="name") @JsonSubTypes({ @JsonSubTypes.Type(value=Lion.class, name="lion"), @JsonSubTypes. Type(value=Tiger.class, name="tiger"), }) 公共接口 Animal { }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.