как я читаю элементы в массиве по одному за раз в responsejs [duplicate]

Функция:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

Тест:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);
800
задан jacefarm 14 October 2017 в 19:13
поделиться

30 ответов

Подумайте об этом, как будто вы просто вызываете функции JavaScript. Вы не можете поставить цикл for внутри вызова функции:

return tbody(
    for (var i = 0; i < numrows; i++) {
        ObjectRow()
    } 
)

Но вы можете сделать массив, а затем передать это в:

var rows = [];
for (var i = 0; i < numrows; i++) {
    rows.push(ObjectRow());
}
return tbody(rows);

Вы можете использовать в основном ту же структуру при работе с JSX:

var rows = [];
for (var i = 0; i < numrows; i++) {
    // note: we add a key prop here to allow react to uniquely identify each
    // element in this array. see: https://reactjs.org/docs/lists-and-keys.html
    rows.push(<ObjectRow key={i} />);
}
return <tbody>{rows}</tbody>;

Кстати, мой пример JavaScript - это почти то, к чему превращается этот пример JSX. Поиграйте с Babel REPL , чтобы понять, как работает JSX.

766
ответ дан caesay 16 August 2018 в 10:33
поделиться
  • 1
    Возможно, компилятор изменился, так как этот пример, похоже, не компилируется в компиляторе jsx , но использование карты, как в ответе FakeRainBrigand ниже, похоже, правильно компилируется. – rav 2 July 2014 в 12:44
  • 2
    Я могу пообещать, что последний пример все еще правильно компилируется на последнем компиляторе JSX. – Sophie Alpert 2 July 2014 в 17:56
  • 3
    Это хорошо работает. Ответ FakeRainBrigand работает для простой итерации массива, но этот ответ необходим для сценариев, в которых вы не можете использовать map (например, у вас нет коллекции, хранящейся в переменной). – Kelvin 8 August 2014 в 17:25
  • 4
    Реагент нуждается в обновлении dom эффективно, в этом случае родитель должен назначить key каждому childern. REF: facebook.github.io/react/docs/… – qsun 2 January 2016 в 23:36
  • 5
    Этот пример будет работать, но он пропускает некоторые важные биты, такие как свойство key, а также стиль кода, который на самом деле не используется в базовых кодах React. Пожалуйста, рассмотрите этот ответ stackoverflow.com/questions/22876978/loop-inside-react-jsx/… как правильный. – okonetchnikov 31 October 2016 в 15:57

Я предпочитаю подход, когда логика программирования происходит за пределами возвращаемого значения render. Это помогает сохранить то, что на самом деле легко получить.

Поэтому я, вероятно, сделаю что-то вроде:

import _ from 'lodash';

...

const TableBody = ({ objects }) => {
  const objectRows = objects.map(obj => <ObjectRow object={obj} />);      

  return <tbody>{objectRows}</tbody>;
} 

По общему признанию, это такой небольшой код, работа хорошо.

7
ответ дан Adam Donahue 16 August 2018 в 10:33
поделиться
  • 1
    Большой поклонник карты lodash для итерации через объекты. Я был бы склонен к import { map } from 'lodash', чтобы вы не импортировали все функции lodash, если они вам не нужны. – Stretch0 8 March 2018 в 12:11
  • 2
    В наши дни нам даже не нужна карта lodash - просто сопоставьте массив непосредственно. – Adam Donahue 9 March 2018 в 23:19
  • 3
    Да, но вы не можете пропустить объект с помощью es6 map(), только массивы. Вот что я сказал, что lodash хорош для перебора объекта. – Stretch0 12 March 2018 в 10:26
  • 4
    Я думал, вы имели в виду objects, как в списке вещей, моя ошибка. – Adam Donahue 13 March 2018 в 14:24

Использование функции отображения массива - очень распространенный способ прокрутки массива элементов и создания компонентов по ним в React, это отличный способ сделать цикл, который довольно эффективен и удобен для выполнения ваших циклов в JSX. не единственный способ сделать это, но предпочтительный путь. Кроме того, не забудьте указать уникальный ключ для каждой итерации по мере необходимости. Функция Map создает уникальный индекс из 0, но не рекомендуется использовать индекс, но если ваше значение уникально или есть уникальный ключ, вы можете использовать их:

<tbody>
  {numrows.map(x=> <ObjectRow key={x.id} />)}
</tbody>

Также несколько строк из MDN if вы не знакомы с функцией отображения на массиве:

map вызывает предоставленную функцию обратного вызова один раз для каждого элемента массива в порядке и создает новый массив из результатов. callback вызывается только для индексов массива, которым присвоены значения, в том числе неопределенные. Он не называется отсутствующими элементами массива (то есть индексы, которые никогда не были установлены, которые были удалены или которым никогда не назначено значение).

обратный вызов вызывается с тремя аргументами: значение элемента, индекс элемента и объект Array, пройденный.

Если для отображения предусмотрен параметр thisArg, он будет использоваться в качестве обратного вызова этого значения. В противном случае значение undefined будет использоваться как его значение. Это значение, в конечном счете наблюдаемое обратным вызовом, определяется в соответствии с обычными правилами для определения этого вида функции.

map не мутирует массив, на который он вызывается (хотя callback, если он вызван, может делать так).

42
ответ дан Alireza 16 August 2018 в 10:33
поделиться

Вот простое решение.

var Object_rows=[];
for (var i=0; i < numrows; i++) {
    Object_rows.push(<ObjectRow/>)
} 
<tbody>
{Object_rows}
</tbody>

Не требуется сопоставление и сложный код. Вам просто нужно нажать строки на массив и вернуть значения для рендеринга.

4
ответ дан Balázs Édes 16 August 2018 в 10:33
поделиться

Если вы решите преобразовать этот метод return () в метод рендеринга, самым простым вариантом будет использование метода map (). Сопоставьте свой массив в синтаксисе JSX с помощью функции map (), как показано ниже ( используется синтаксис ES6 ).


Внутренний родительский компонент:

<tbody> { objectArray.map((object, index) => <ObjectRow key={index} object={object}>) } </tbody>

Обратите внимание, что атрибут key добавлен в ваш дочерний компонент. Если вы не указали ключевой атрибут, вы можете увидеть следующее предупреждение на своей консоли.

Предупреждение. Каждый дочерний элемент в массиве или итераторе должен иметь уникальную «ключевую» опору.


Теперь в компоненте ObjectRow вы можете получить доступ к объекту из его свойств.

Внутри компонента ObjectRow

const { object } = this.props

или

const object = this.props.object

Это должно привести вам объект, который вы передали от родительского компонента к переменной object в компоненте ObjectRow. Теперь вы можете выплеснуть значения в этом объекте в соответствии с вашей целью.


Ссылки:

метод map () в Javascript

ECMA Script 6 или ES6

10
ответ дан bharadhwaj 16 August 2018 в 10:33
поделиться

Вы также можете извлечь вне обратного блока:

render: function() {
    var rows = [];
    for (var i = 0; i < numrows; i++) {
        rows.push(<ObjectRow key={i}/>);
    } 

    return (<tbody>{rows}</tbody>);
}
26
ответ дан Brandon Sibeitokgong 16 August 2018 в 10:33
поделиться

Просто используйте map метод Array с синтаксисом ES6:

<tbody>
  {items.map(item => <ObjectRow key={item.id} name={item.name} />)} 
</tbody>

Не забудьте свойство key.

52
ответ дан danielfeelfine 16 August 2018 в 10:33
поделиться

Функция ES2015 / Babel использует функцию генератора для создания массива JSX:

function* jsxLoop(times, callback)
{
    for(var i = 0; i < times; ++i)
        yield callback(i);
}

...

<tbody>
    {[...jsxLoop(numrows, i =>
        <ObjectRow key={i}/>
    )]}
</tbody>
10
ответ дан David Q Hogan 16 August 2018 в 10:33
поделиться

ES2015 Array.from с функцией map + key

Если у вас нет .map(), вы можете использовать Array.from() с mapFn для повторения элементов:

<tbody>
  {Array.from({ length: 5 }, (v, k) => <ObjectRow key={k} />)}
</tbody>
8
ответ дан Do Async 16 August 2018 в 10:33
поделиться

Ваш код JSX будет скомпилирован в чистый код JavaScript, любые теги будут заменены объектами ReactElement. В JavaScript вы не можете вызывать функцию несколько раз для сбора возвращаемых переменных.

Это незаконно, единственный способ - использовать массив для хранения возвращаемых функций.

Или вы можете использовать Array.prototype.map , который доступен , так как JavaScript ES5 обрабатывает эту ситуацию.

Возможно, мы сможем написать другой компилятор, чтобы воссоздать новый синтаксис JSX для реализации функции повторения, аналогичной Угловой ng-repeat .

9
ответ дан Emile Bergeron 16 August 2018 в 10:33
поделиться

Я знаю, что это старый поток, но вы можете проверить http://wix.github.io/react-templates/ , что позволяет использовать шаблоны jsx-стиля в реакции , с несколькими директивами (например, rt-repeat).

Ваш пример, если вы использовали шаблоны реакции, будет:

<tbody>
     <ObjectRow rt-repeat="obj in objects"/>
</tbody>
20
ответ дан Etai 16 August 2018 в 10:33
поделиться

Я использую это:

gridItems = this.state.applications.map(app =>
                            <ApplicationItem key={app.Id} app={app } />
                            );

PD: никогда не забывайте ключ или у вас будет много предупреждений!

10
ответ дан J C 16 August 2018 в 10:33
поделиться
  • 1
    Или используйте индекс массива, если ваши объекты не имеют свойства .Id, например items.map( (item, index) => <Foo key={index}>{item}</Foo> – kontur 30 March 2017 в 09:26

скажем, у нас есть массив элементов в вашем состоянии:

[{name: "item1", id: 1}, {name: "item2", id: 2}, {name: "item3", id: 3}]

<tbody>
    {this.state.items.map((item) => {
        <ObjectRow key={item.id} name={item.name} />
    })} 
</tbody>
12
ответ дан Jan Franz Palngipang 16 August 2018 в 10:33
поделиться
  • 1
    Я думаю, вам может понадобиться избавиться от {} после карты (элемента), которая, казалось, сработала для меня. – Ian 10 December 2016 в 18:22

Чтобы циклически повторяться и возвращаться, вы можете достичь этого с помощью from и map :

  <tbody>
    {
      Array.from(Array(i)).map(() => <ObjectRow />)
    }
  </tbody>

, где i = number of times

5
ответ дан Jee Mok 16 August 2018 в 10:33
поделиться

Просто используйте .map() для прокрутки вашей коллекции и возврата <ObjectRow> элементов с реквизитами с каждой итерации.

Предполагая, что objects является массивом где-то ...

<tbody>
  { objects.map((obj, index) => <ObjectRow obj={ obj } key={ index }/> ) }
</tbody>
11
ответ дан Joshua Michael Calafell 16 August 2018 в 10:33
поделиться

, вы можете, конечно, решить с помощью .map, как было предложено другим ответом. Если вы уже используете babel, вы можете подумать об использовании jsx-control-statements Они требуют немного настройки, но я думаю, что это стоит с точки зрения удобочитаемости (особенно для нереактивного разработчика). Если вы используете linter, есть также команды eslint-plugin-jsx-control-statements

9
ответ дан Jurgo Boemo 16 August 2018 в 10:33
поделиться

, если numrows - это массив, и это очень просто.

<tbody>
   {numrows.map(item => <ObjectRow />)}
</tbody>

Тип данных Array в React очень хорош, массив может возвращать новый массив и поддерживать фильтр, уменьшать и т. д.

15
ответ дан lulin 16 August 2018 в 10:33
поделиться
  • 1
    Это не достойный ответ, так как он не использует ключ. – kojow7 20 September 2017 в 21:55

Если вы уже используете lodash, функция _.times удобна.

import React, { Component } from 'react';
import Select from './Select';
import _ from 'lodash';

export default class App extends Component {
    render() {
        return (
            <div className="container">
                <ol>
                    {_.times(3, i =>
                        <li key={i}>
                            <Select onSelect={this.onSelect}>
                                <option value="1">bacon</option>
                                <option value="2">cheez</option>
                            </Select>
                        </li>
                    )}
                </ol>
            </div>
        );
    }
}
33
ответ дан mpen 16 August 2018 в 10:33
поделиться
  • 1
    Array.prototype.map может быть отличным вариантом, если вы не включаете библиотеку, такую ​​как lodash. [Д0] developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . – Isaiah Grey 24 December 2015 в 19:28
  • 2
    @IsaiahGrey Только если у вас уже есть массив. Иногда вы просто хотите повторить материал несколько раз. – mpen 24 December 2015 в 19:29
  • 3
    конечно же! Лоты разных подходов наверняка зависят от фактических данных. Я обнаружил, что чаще всего в нашем процессе разработки мы смогли подгонять карту из-за того, как моделируются данные. Отличный пример использования lodash! Кстати, вы используете синтаксис инициализатора свойств, чтобы привязать свои методы к вашим компонентам? – Isaiah Grey 24 December 2015 в 19:33
  • 4
    @IsaiahGrey Я думаю, что они просто называются определениями метода ES6 – mpen 22 February 2016 в 17:39

Вы можете сделать что-то вроде:

let foo = [1,undefined,3]
{ foo.map(e => !!e ? <Object /> : null )}
4
ответ дан Pang 16 August 2018 в 10:33
поделиться

Вы также можете использовать функцию самозапуска:

return <tbody>
           {(() => {
              let row = []
              for (var i = 0; i < numrows; i++) {
                  row.push(<ObjectRow key={i} />)
              }
              return row

           })()}
        </tbody>
15
ответ дан Phillip 16 August 2018 в 10:33
поделиться
  • 1
    Использование анонимных функций внутри рендера не считается хорошей практикой в ​​реагировании, так как эти функции необходимо воссоздавать или отбрасывать при каждом повторном рендеринге. – Vlatko Vlahek 29 September 2017 в 07:25
  • 2
    это не повлияет на производительность в этом примере. – degr 12 October 2017 в 13:44

Не уверен, что это сработает для вашей ситуации, но часто map - хороший ответ.

Если это был ваш код с циклом for:

<tbody>
    for (var i=0; i < objects.length; i++) {
        <ObjectRow obj={objects[i]} key={i}>
    } 
</tbody>

Вы можете записать это так: map :

<tbody>
    {objects.map(function(object, i){
        return <ObjectRow obj={object} key={i} />;
    })}
</tbody>

Синтаксис ES6:

<tbody>
    {objects.map((object, i) => <ObjectRow obj={object} key={i} />)}
</tbody>
645
ответ дан Remco Haszing 16 August 2018 в 10:33
поделиться
  • 1
    Карта имеет больше смысла, если итерация является массивом; Цикл for подходит, если это число. – Code Whisperer 26 April 2015 в 18:40
  • 2
    <tbody>{objects.map((o, i) => <ObjectRow obj={o} key={i}/>}</tbody> с помощью поддержки Reactify ES6 или Babel. – Steve Taylor 27 July 2015 в 10:24
  • 3
    +1. Я даже использую это с ul (неупорядоченный список). <ul> {objects.map((object:string,i:number)=>{ return <li>{object}</li> })} </ul> с использованием TypeScript – Roberto C Navarro 28 September 2015 в 20:10
  • 4
    это здорово, но вы не можете сопоставить объект. Для этого я бы использовал for..in – Damon 15 January 2016 в 20:09
  • 5
    Имейте в виду, что порядок ключей произволен при использовании Object.keys. Я обнаружил, что хранение порядка ключей по отдельности работает хорошо, а также порядок на объектном литерале, если это необходимо. Это позволяет мне писать код типа this.props.order.map((k)=><ObjectRow key={k} {...this.props.items[k]} />) – tgrrr 15 March 2016 в 09:04

Я использую его как

<tbody>
{ numrows ? (
   numrows.map(obj => { return <ObjectRow /> }) 
) : null}
</tbody>
6
ответ дан Sampath 16 August 2018 в 10:33
поделиться

Вот пример из React doc: https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions-as-children

function Item(props) {
  return <li>{props.message}</li>;
}

function TodoList() {
  const todos = ['finish doc', 'submit pr', 'nag dan to review'];
  return (
    <ul>
      {todos.map((message) => <Item key={message} message={message} />)}
    </ul>
  );
}

как ваш случай, я предлагаю написать вот так:

function render() {
  return (
    <tbody>
      {numrows.map((roe, index) => <ObjectRow key={index} />)}
    </tbody>
  );
}

Обратите внимание, что ключ очень важен, потому что React использует Key для отличия данных в массиве.

4
ответ дан Sinka Lee 16 August 2018 в 10:33
поделиться

Если у вас еще нет массива на map(), например, ответа @ FakeRainBrigand, и хотите вставить его таким образом, чтобы исходный макет соответствовал выходному сигналу ближе, чем ответ @ SophieAlpert:

С ES2015 ( ES6) [расширенные и стрелочные функции]

http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview

<tbody>
  {[...Array(10)].map((x, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

Re: указывает, что Array.from требуется для распространения, но в настоящее время (v5.8.23), который, похоже, не имеет места при распространении фактического Array. У меня есть проблема документации , чтобы выяснить это. Но используйте на свой страх и риск или полипол.

Vanilla ES5

Array.apply

<tbody>
  {Array.apply(0, Array(10)).map(function (x, i) {
    return <ObjectRow key={i} />;
  })}
</tbody>

Inline IIFE

http://plnkr.co/edit/4kQjdTzd4w69g8Suu2hT?p=preview

<tbody>
  {(function (rows, i, len) {
    while (++i <= len) {
      rows.push(<ObjectRow key={i} />)
    }
    return rows;
  })([], 0, 10)}
</tbody>

Комбинирование методов из других ответов

Хранить исходный макет, соответствующий выходному , но сделайте внутреннюю часть более компактной:

render: function () {
  var rows = [], i = 0, len = 10;
  while (++i <= len) rows.push(i);

  return (
    <tbody>
      {rows.map(function (i) {
        return <ObjectRow key={i} index={i} />;
      })}
    </tbody>
  );
}

С синтаксисом ES2015 & amp; Array методы

С помощью Array.prototype.fill вы могли бы сделать это как альтернативу использованию спреда, как показано выше:

<tbody>
  {Array(10).fill(1).map((el, i) =>
    <ObjectRow key={i} />
  )}
</tbody>

(я думаю, вы действительно могли бы опустить любой аргумент fill(), но я не на это 100%.) Благодаря @FakeRainBrigand для исправления моей ошибки в более ранней версии решения fill() (см. ревизии).

key

Во всех случаях key attr устраняет предупреждение с помощью сборки разработки, но недоступно для ребенка. Вы можете передать дополнительный attr, если хотите, чтобы индекс был доступен в дочернем элементе. См. Списки и ключи для обсуждения.

319
ответ дан Sophie Alpert 16 August 2018 в 10:33
поделиться
  • 1
    Как насчет yield? Нажатие элементов в промежуточную матрицу является отвратительным, когда мы имеем генераторы. Они работают? – mpen 12 September 2015 в 05:58
  • 2
    @Mark Я не знаю, что генераторы действительно применимы здесь. Ключевым моментом для этого в контексте JSX является выражение, которое возвращает массив. Поэтому, если вы собираетесь использовать генератор, вы, вероятно, все равно его распространите, и, вероятно, он будет более подробным, чем решения на базе ES2015. – JMM 12 September 2015 в 11:56
  • 3
    Как этот более подробный? И почему бы JSX не принимать какие-либо итеративные, а не только массивы? – mpen 12 September 2015 в 17:34
  • 4
    @Mark Это действительно less verbose, чем пример IIFE (ES5), который я использовал, но он значительно более подробный, чем версия [...Array(x)].map(() => <El />)), которая, по моему мнению, самая элегантная, и почему я ее показал. Re: Второй вопрос, это отличный момент. Кажется, что ничего не происходит в JSX, что исключает его, поэтому это зависит от того, что React или другой потребитель преобразованного JSX делает с дочерними аргументами, о которых я не мог сказать, не глядя на источник. Вы знаете? Это интригующий вопрос. – JMM 12 September 2015 в 19:49
  • 5
    @corysimmons Cool, спасибо за информацию об fill(). Теперь я помню, что причина, по которой я колебалась, - это вопрос о том, как в спецификации ES указывается опциональность параметров (нужно что-то задуматься). Запятая - это просто способ элиминировать элемент массива - в этом случае первый. Вы можете сделать это, если хотите, чтобы индексы находились от 1..length массива, который вы распространяете, а не 0..length-1 массива с расширением (поскольку элементы с уменьшенными элементами просто вносят вклад в длину массива и не позволяют, t имеют соответствующее свойство). – JMM 25 October 2016 в 15:29

Существует несколько способов сделать это. JSX в конечном итоге скомпилируется в JavaScript, поэтому, пока вы пишете действующий JavaScript, вы будете хорошо.

Мой ответ направлен на объединение всех замечательных способов, уже представленных здесь:

Если у вас нет массива объекта, просто количество строк:

в блоке return, создавая Array и используя Array.prototype.map:

render() {
  return (
    <tbody>
      {Array(numrows).fill(null).map((value, index) => (
        <ObjectRow key={index}>
      ))}
    </tbody>
  );
}

вне блока return, просто используйте обычный JavaScript for-loop:

render() {
  let rows = [];
  for (let i = 0; i < numrows; i++) {
    rows.push(<ObjectRow key={i}/>);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

сразу вызывается выражение функции:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < numrows; i++) {
          rows.push(<ObjectRow key={i}/>);
        }
        return rows;
      }}
    </tbody>
  );
}

Если у вас есть массив объектов

в блоке return, .map() каждый объект к компоненту <ObjectRow>:

render() {
  return (
    <tbody>
      {objectRows.map((row, index) => (
        <ObjectRow key={index} data={row} />
      ))}
    </tbody>
  );
}

вне блока return, просто используйте обычный JavaScript for- loop:

render() {
  let rows = [];
  for (let i = 0; i < objectRows.length; i++) {
    rows.push(<ObjectRow key={i} data={objectRows[i]} />);
  } 
  return (
    <tbody>{rows}</tbody>
  );
}

сразу вызывается функциональное выражение:

render() {
  return (
    <tbody>
      {() => {
        let rows = [];
        for (let i = 0; i < objectRows.length; i++) {
          rows.push(<ObjectRow key={i} data={objectRows[i]} />);
        }
        return rows;
      }}
    </tbody>
  );
}
5
ответ дан Yangshun Tay 16 August 2018 в 10:33
поделиться

Большой вопрос.

Что я делаю, когда хочу добавить определенное количество компонентов, используйте вспомогательную функцию.

Определите функцию, которая возвращает JSX:

const myExample = () => {
    let myArray = []
    for(let i = 0; i<5;i++) {
        myArray.push(<MyComponent/>)
    }
    return myArray
}

//... in JSX

<tbody>
    {myExample()}
</tbody>
15
ответ дан Phillip 16 August 2018 в 10:34
поделиться
15
ответ дан Phillip 6 September 2018 в 05:02
поделиться
15
ответ дан Phillip 6 September 2018 в 05:02
поделиться
16
ответ дан Phillip 29 October 2018 в 11:38
поделиться
16
ответ дан Phillip 29 October 2018 в 11:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: