计数出现在整个对象中包含的值substring

发布于 2025-02-03 02:48:34 字数 815 浏览 2 评论 0原文

我想计算对象值的 substring ,即整个对象包含一个字符串而不是键 equals equals a字符串。 XSLT中的工作XPath将是

count(// v [contrains(。,current-grouping-key())])

但我无法在JavaScript中弄清楚这一点。

我尝试了以下内容:

const obj = 
  [ { v: 'Bla Blu Bli' },
    { v: 'Bla Blu Bli' },
    { v: 'Bla Blu' },
    { v: 'Bla Bli' }
  ];

const count = obj.reduce( function(sums,entry) {
    sums[entry.v] = (sums[entry.v] || 0) + 1;
    return sums;
 },{});
 
console.log(count)

但这仅计算确切的字符串。 所以我得到:

"Bla Blu Bli": 2,
"Bla Blu": 1,
"Bla Bli": 1

有没有

 "Bla Blu Bli": 2,
 "Bla Blu": 3,
 "Bla Bli": 3

办法计算子字代替确切值?

I want to count substrings of object values, i.e. the entire object contains a string instead of a key equals a string.
A working Xpath in XSLT would be

count(//v[contains(.,current-grouping-key())])

But i can't figure this out in javascript.

I tried the following:

const obj = 
  [ { v: 'Bla Blu Bli' },
    { v: 'Bla Blu Bli' },
    { v: 'Bla Blu' },
    { v: 'Bla Bli' }
  ];

const count = obj.reduce( function(sums,entry) {
    sums[entry.v] = (sums[entry.v] || 0) + 1;
    return sums;
 },{});
 
console.log(count)

But this counts the exact strings only.
So I get:

"Bla Blu Bli": 2,
"Bla Blu": 1,
"Bla Bli": 1

instead of

 "Bla Blu Bli": 2,
 "Bla Blu": 3,
 "Bla Bli": 3

Is there a way to count the substrings instead of the exact values?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

長街聽風 2025-02-10 02:48:34

第二版应该更快。

(您写了我有100k+ values ,在评论中)

它仅创建一个不同的系列的数组,与相同系列的副本相关联
并通过将此数量添加到包括相同值的其他集合的数量中来遍历此数组,
通过仅选择大小较大的人。

我之所以使用集元素,是因为根据DOC A [set] .has(value)比[数组]更快。

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Bli Blu' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .reduce((r,o) => // create arr with unique sets with count of copies
    {
    let 
      arr = o.v.split(' ')
    , sam = r.find(x=>(x.s.size===arr.length) && arr.every(a=>x.s.has(a)) )
      ;
    if (sam)  ++sam.n   // + one more copy
    else      r.push({arr, s:new Set(arr), n:1 })
       // next step need  arr and set to avoid losing time 
       // in conversion operations between array and Set
    return r
    },[]) 
  .reduce((c,e,_,all) =>
    {
    c[e.arr.join(' ')] = e.n  
      + all.reduce((s,x)=>((x.s.size > e.s.size && e.arr.every(a=>x.s.has(a))) ? s + x.n : s),0)
      // try to find includings, only in largest sets
    return c
    },{})  

console.log(  counts  )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

This second version should be faster.

(you wrote I have 100k+ values , in a comment)

It creates an array only of different series, associated with the number of copies of identical series
And traverses this array by adding to this quantity those of the other sets including the same values,
by selecting only those whose size is larger.

I used Set elements because according to the doc a [set].has(value) is faster than an [array].includes(value)

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Bli Blu' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .reduce((r,o) => // create arr with unique sets with count of copies
    {
    let 
      arr = o.v.split(' ')
    , sam = r.find(x=>(x.s.size===arr.length) && arr.every(a=>x.s.has(a)) )
      ;
    if (sam)  ++sam.n   // + one more copy
    else      r.push({arr, s:new Set(arr), n:1 })
       // next step need  arr and set to avoid losing time 
       // in conversion operations between array and Set
    return r
    },[]) 
  .reduce((c,e,_,all) =>
    {
    c[e.arr.join(' ')] = e.n  
      + all.reduce((s,x)=>((x.s.size > e.s.size && e.arr.every(a=>x.s.has(a))) ? s + x.n : s),0)
      // try to find includings, only in largest sets
    return c
    },{})  

console.log(  counts  )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

独留℉清风醉 2025-02-10 02:48:34

您可以使用它:

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .map(e=>e.v.split(' ').sort((a,b)=>a.localeCompare(b)))
  .reduce((r,a,_,all)=>
    {
    let terms = a.join(' ')
    if (!r[terms])
      r[terms] = all.reduce((c,x)=>c+(a.every(v=>x.includes(v))?1:0),0);
    return r
    },{})
    
console.log(  counts )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

you can use that:

const obj = 
  [ { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu Bli' }
  , { v: 'Bla Blu'     }
  , { v: 'Bla Bli'     }
  ];

const counts = obj
  .map(e=>e.v.split(' ').sort((a,b)=>a.localeCompare(b)))
  .reduce((r,a,_,all)=>
    {
    let terms = a.join(' ')
    if (!r[terms])
      r[terms] = all.reduce((c,x)=>c+(a.every(v=>x.includes(v))?1:0),0);
    return r
    },{})
    
console.log(  counts )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}

小嗷兮 2025-02-10 02:48:34

您必须使用索引或类似的索引,以查看字符串中是否存在子字符串。

例子:

obj = [
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu"
    }
]

const counts = Object.fromEntries(
  obj.map(({v}) => [v, obj.reduce((acc, el) => {
    if (el.v.indexOf(v) > -1) acc++;
    return acc;
  }, 0)])
);

console.log(counts);

You have to use indexOf or similar, to see if a substring exists in a string.

Example:

obj = [
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu † Bli"
    },
    {
        "v": "Bla † Blu"
    }
]

const counts = Object.fromEntries(
  obj.map(({v}) => [v, obj.reduce((acc, el) => {
    if (el.v.indexOf(v) > -1) acc++;
    return acc;
  }, 0)])
);

console.log(counts);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文