按字母顺序渲染名称列表,并按其第一个字符

时间:2018-06-07 19:46:46

标签: javascript reactjs

我需要按字母顺序呈现名称列表,并按每个名称的起始字母分组。它应该是这样的:

**A**

Anders
Anton
Angela

**B**

Brian
Bernard

**C**

Carl

我当前的解决方案可以对对象中包含的所有名称进行排序,但是我无法在起始名称之前添加起始字母(例如渲染' A'以上' Anders& #39;以及' B'以上' Brian')

当前解决方案:

completeEmpList = empList
  .sort((a, b) => a.Name.localeCompare(b.Name))
    .map((emp) => (
      <div> {emp.Name} </div>
    ))

不应该处理超过300个元素的数据,因此在这种情况下优化并不重要。

5 个答案:

答案 0 :(得分:1)

您可以先排序,然后使用reduce创建一个对象,并按每个名称的第一个字符对值进行分组。

class Example extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      items: [{ Name: "Carl" },{ Name: "Anders" },{ Name: "Anton" },{ Name: "Brian" },{ Name: "Bernard" },{ Name: "Angelaa" }]
    }
  }
  
  render() {
    const group = this.state.items
    .sort((a, b) => a.Name.localeCompare(b.Name))
    .reduce((r, e) => {
      const key = e.Name[0];
      if(!r[key]) r[key] = []
      r[key].push(e);
      return r;
    }, {});
    
    return <div>
    {Object.entries(group)
      .map(([key, value], i) => {
        return <div key={i}>
          <strong>{key}</strong>
          {value.map((item, j) => <div key={j}>{item.Name}</div>)}
        </div>
      })}
      </div>
    }
  }

  ReactDOM.render(<Example />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

答案 1 :(得分:0)

您可以尝试以下代码:

completeEmpList = empList
  .sort((a, b) => a.Name.localeCompare(b.Name))
  .map((emp, index, array) => (
    <div> 
      { array[index - 1].Name[0].localeCompare( emp.Name[0] ) === -1?
        <p>** { emp.Name[0] } **</p>
      }
      {emp.Name}
    </div>
  ))

答案 2 :(得分:0)

在评论的一些指导下,我使用了这段代码:

let previousChar = ''

if (empList) {
  completeEmpList = empList
    .sort((a, b) => a.Name.localeCompare(b.Name))
    .map((emp) => {
      if (emp.Name.charAt(0) !== previousChar) {
        previousChar = emp.Name.charAt(0)
        return (
            <div>
              <div className='charElement' key={'c' + emp.Id}> emp.Name.charAt(0)}</div>
            </div>              
              <div className='empName'>{emp.Name}</div>
            </div>
          </div>
        )
      } else {
        return (
          <div className='empName'>{emp.Name}</div>
        )
      }
    })

答案 3 :(得分:0)

考虑这个问题的另一种方法是首先进行一些数据处理,将数据转换为方便的格式,然后再创建视图。假设您知道如何从中生成视图,我认为有用的格式可能是数组数组,每个首字母都有一个内部数组,如

[["Anders", "Angela", "Anton"], ["Bernard", "Brian"], ["Carl"]]

要创建它,您可以使用自定义解决方案,但有一个合理的抽象可能更容易编写。因此,此版本创建函数groupWith,该函数接受一个函数,该函数本身接受两个连续的值并响应它们是否属于同一组,在本例中仅为(a, b) => a.charAt(0) == b.charAt(0)

const groupWith = (fn, list) => list.slice(1).reduce(
  (all, curr) => fn(all[all.length - 1][0], curr) 
    ? all.slice(0, -1).concat([all[all.length - 1].concat(curr)])
    : all.concat([[curr]]), 
  [[list[0]]]
)

const names = ['Brian', 'Anders', 'Angela', 'Carl', 'Anton', 'Bernard'];

const groups = groupWith((a, b) => a.charAt(0) == b.charAt(0), names.sort())

console.log(groups)

groupWith函数可以在您的项目中重复使用,它可以将杂乱的内容从更重要的代码中抽象出来。

答案 4 :(得分:0)

字符串不变性使摊销变得重要。

我知道你说优化并不重要,但是,我认为在使用Strings时非常重要。原因是&#34; 不变性&#34;。如果允许他们的算法在每次迭代时重写字符串,那么很容易以二次摊销时间结束。使用集合,并使用必要的格式(换行符等)将字符串插入到该集合中是最便宜和最便宜的方式。

&#13;
&#13;
const names = ['Brian', 'Anders', 'Angela', 'Carl', 'Anton', 'Bernard'];

// Create a primative hashtable with the Alphabetized letter as your key.
// Your value for that key, is a collection of the Names.
const memo = names.reduce((memo, name) => {
  if (name[0] in memo) memo[name[0]].push(name);     // if the first letter in the name has already been recorded, then add it to the collection in that letter.
  else memo[name[0]] = [name];                       // if the first letter has yet to be added to the memo, add the letter and assign createa a new collection of names.

  return memo;
}, {});
console.log('memo: ', memo)

// Now iterate over your memoized collection.
// Strings are immutable so using arrays of individual words are best for the 
// lowest runtime. Otherwise, you'll have quadratic amortized time.
const answer = Object
  .keys(memo)
  .sort()                              // Sort the memo keys to ensure alphabetical order.
  .reduce((a, letter) => {             // Reduce a memo {object} into an array...
    const letterList = memo[letter]    // Create new array of names.
      .sort()                          // sorting the array of names.
      .map((name) => name);            // Return each name into the array.

    letterList.unshift(`**${letter}**`, '\n');  // "unshift" puts the insertion value in the front of the collection.
    letterList.push('\n');                      // add a newline to the end of the array to seperate the individual letter groups.

  a = a.concat(letterList);                     // add the finished Letter array to the overall collection of all names.

  return a;
}, [])
.join('\n');                                    // Join on newline so that you don't have to re-write the entire string due to immutability.

console.log('Answer: \n', answer);
&#13;
&#13;
&#13;