簡體   English   中英

給定一個對象數組,計算定義了多少個(可能不同的)屬性

[英]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 reviverJSON.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM