9
<table>
   <tbody>
   {this.state.data.map((person, i) => <TableRow key = {i} data = {person} />)}
   </tbody>
</table>

This maps my entire array, but how would I map from a minimum index to a maximum index? So say my array has 500 elements. I want to map this array (of data) from index 15 to 24 inclusive. (So I'd only have 10 elements on my screen).

edit: these answers are interesting.. but no mention of .filter() though? I saw that it might help what I want but I'm trying to figure out how to do it in react.

0

3 Answers 3

8

Use Array#slice() to extract a shallow copy of the values you want from this.state.data.

const SubsetTable = props => {
  let {startIndex, endIndex, data} = props

  let subset = data.slice(startIndex, endIndex)

  return (
   <table>
     <tbody>
       {subset.map((person, i) => (<TableRow key = {i} data = {person} />)}
     </tbody>
   </table>
  )
}

// Since splice() is inclusive of the range given, you'll need to 
// adjust your range to include that last index if needed
// The below will grab all values in indexes 15-24, 
<SubsetTable startIndex={15} endIndex={25} data={this.state.data} />

Since you've updated your question, regarding use of Array#filter(), filter() requires that you iterate over the entire set. Array#slice() is only going to extract the contiguous index range that you'd like extract. filter() is better when you gave a condition that you want all your Array data members to meet and and your collection is unordered.

Sign up to request clarification or add additional context in comments.

1 Comment

15 to 24 inclusive. Remember, Array.prototype.slice goes up to, but not including the last index. data.slice(startIndex, endIndex + 1) :)
4

However you set the min/max (let's assume state)

this.state = {
    min: 15,
    max: 24,
};

You just adjust your map to an if statement to return if the index (i) is greater than or equal to the min, and less than or equal to the max.

{this.state.data.map((person, i) => {
    if (i >= this.state.min && i <= this.state.max) {
        return (<TableRow key = {i} data = {person} />);
    }
})}

Now, we can be real here and say this is inefficient. So, after you have reached the max, break out of the loop, which may require a different loop type since I think you can't break from a map

10 Comments

not sure what it will affect, but this method will return array with undefined values at indexes <15 and >24.
@GiorgiMoniava was just typing that myself. Pretty sure React would prefer those values to be null instead.
@peteb Yes, I agree I don't know how react will react to that. otherwise it is also not a very bad solution.
@GiorgiMoniava I didn't even think about that, I think if we want efficiency here, a simple for loop will work best because it will retain O(n) notation while being able to break out once it reaches the max.
@Sagivb.g You don't have to return it, before return statement in render, you push JSX elements in a variable (say in for loop) and render that variable then. (I will upvote this answer for its simplicity ;) though not sure how undefined values will affect things :)).
|
2

The problem here is that Array.prototype.map must return the exact same length of the array.
So you need to do some filtering and mapping again.

To minimize the number of loops and iterations, i would use Array.prototype.reduce, which will let you do both filtering and mapping in the same iteration.

Running example:

const persons = [
  { value: 'John', id: 1 },
  { value: 'Jane', id: 2 },
  { value: 'Mike', id: 3 },
  { value: 'Nikol', id: 4 },
  { value: 'Bob', id: 5 },
  { value: 'Dave', id: 6 },
]

const TableRow = ({ data }) => <tr><td>{data.value}</td></tr>

const start = 2;
const end = 4;

const App = () => (
  <div >
    <table>
      <tbody>
        {
          persons.reduce((result, current, i) => {
            if (i >= start && i <= end) { // 0 based don't forget!
              const row = (<TableRow key={i} data={current} />);
              result.push(row);
            }
            return result;
          }, [])
        }
      </tbody>
    </table>
  </div>
);

ReactDOM.render(<App />, document.getElementById('root'));
<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="root"></div>

2 Comments

A consideration when comparing slice() and reduce(); reduce() will be slower than slice() for larger sets when you have a small range that you're extracting. Its cheaper to grab only the items needed and then iterate over that smaller set using map(). Instead, reduce() will always need to iterate over all elements within the set even if that element isn't in the range. The performance gain for reduce() is when you know you need to reduce an entire set of items and perform an operation against items within the reduced set.
Abusing reduce to handle all the logic at once is much less readable (and not provably faster, with inlining) than some of the other answers. There is nothing functional about pushing from a reduce, that is a horrible smell. This is just a for loop by another name, not a meaningful reduce.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.