【问题标题】:javascript: in a chain, how to get size of previous array?javascript:在链中,如何获取先前数组的大小?
【发布时间】:2018-11-09 00:06:53
【问题描述】:

链接filter和reduce时,如何获取过滤后数组的大小?我需要这个尺寸来定制响应式设计 CSS。 我的(简化的)代码,使用回调的第三和第四个参数:

json.articles
.filter(a => keep(a,name))
.reduce((el, a,i,t) =>
    i===0? DOMtag('section',{'class':`media${t.length}`})
        .appendChild(DOMtag(`article`, content(a,0))).parentElement
    : el.appendChild(DOMtag(`article`, content(a,i))).parentElement,
    null);

或者,甚至更简单(感谢 luc 和他在下面的懒惰评估建议):

json.articles
.filter(a => keep(a,name))
.reduce((el, a,i,t) =>
    (el || DOMtag('section',{'class':`media${t.length}`}))
        .appendChild(DOMtag(`article`, content(a,i))).parentElement,
    null);

两个代码都可以,但是如果有人想以某种方式绑定this,则可以使用累加器的初始值,例如:

json.articles
.filter(a => keep(a,name))
.reduce((el, a) =>
    el.appendChild(DOMtag(`article`, content(a,i))).parentElement,
    DOMtag('section',{'class':`media${this.length}`}));

有什么想法吗?

【问题讨论】:

标签: javascript arrays this method-chaining


【解决方案1】:

在传递reduce 的默认值时无法访问过滤后的数组长度,因为在调用reduce 之前计算表达式。

不过,您可以将函数的内容简化如下:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);

  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:
const section = json.articles
  .filter(a => a.name)
  .map(a => DOMTag(`article`, {content: a.name}))
  .reduce((p, c, i, a) =>
    (p || DOMTag('section',{className:`media${a.length}`}))
      .appendChild(c).parentElement
      , null);

section.className = `media${section.childNodes.length}`

// Validation
console.log(section.outerHTML);    

另一个干净的选项是将className设置在链之外:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, content) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  return tag;
}

// Start of actual answer code:
const section = json.articles
  .filter(a => a.name)
  .map(el => DOMTag('article', el.name))
  .reduce((p,c) => (p.appendChild(c), p), DOMTag('section'))

section.className = `media${section.childNodes.length}`

// Validation
console.log(section.outerHTML);

选项2:使用函数抽象容器的创建:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:

function section(children) {
  const section = DOMTag('section', {
    className: `media${children.length}`
  });
  children.forEach(c => section.appendChild(c));
  return section;
}

const s = section(
  json.articles
    .filter(a => a.name)
    .map(el => DOMTag('article', {content: el.name}))
)

// Validation
console.log(s.outerHTML);

选项3:更多功能!如果你绝对必须使用reduce:

// Sample data
const json = {articles: [{name: 'test'},{},{name: 'test2'},{},]};
// functional helper function to illustrate the example
function DOMTag(tagName, {content, className}) {
  const tag = document.createElement(tagName);
  if (content) {
    tag.appendChild(document.createTextNode(content));
  }
  if (className) {
    tag.className = className;
  }
  return tag;
}

// Start of actual answer code:

function defaultSection() {
  let m = false;
  return (a = []) => {
    if (!m) {
      m = DOMTag('section', {className: `media${a.length}`});
    }
    return m;
  };
}

const section = json.articles
  .filter(a => a.name)
  .map(el => DOMTag('article', {content: el.name}))
  .reduce((p,c,i,a) => {
    p(a).appendChild(c);
    return p;
  }, defaultSection())();

// Validation
console.log(section.outerHTML);

【讨论】:

  • 有一种方法可以将数组传递给回调(同步回调),因此我相信应该有一种方法可以将this 绑定到该数组。您的解决方法 #2 和 #3 很有趣(#1 不可链接),但并不比我自己的第一个解决方案好多少。
  • 这是一个公平的观点。我不认为您可以按照您的想法使用bind,但您可以利用布尔表达式的惰性求值来简化您的初始代码。用一个可能也很有趣的新选项更新答案。
  • 我不明白为什么这个答案被否决了。至少上面的评论很有用。
猜你喜欢
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2017-01-18
  • 2011-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多