Функция:
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);
Подумайте об этом, как будто вы просто вызываете функции 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.
Я предпочитаю подход, когда логика программирования происходит за пределами возвращаемого значения render
. Это помогает сохранить то, что на самом деле легко получить.
Поэтому я, вероятно, сделаю что-то вроде:
import _ from 'lodash';
...
const TableBody = ({ objects }) => {
const objectRows = objects.map(obj => <ObjectRow object={obj} />);
return <tbody>{objectRows}</tbody>;
}
По общему признанию, это такой небольшой код, работа хорошо.
import { map } from 'lodash'
, чтобы вы не импортировали все функции lodash, если они вам не нужны.
– Stretch0
8 March 2018 в 12:11
map()
, только массивы. Вот что я сказал, что lodash хорош для перебора объекта.
– Stretch0
12 March 2018 в 10:26
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, если он вызван, может делать так).
blockquote>
Вот простое решение.
var Object_rows=[];
for (var i=0; i < numrows; i++) {
Object_rows.push(<ObjectRow/>)
}
<tbody>
{Object_rows}
</tbody>
Не требуется сопоставление и сложный код. Вам просто нужно нажать строки на массив и вернуть значения для рендеринга.
Если вы решите преобразовать этот метод 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. Теперь вы можете выплеснуть значения в этом объекте в соответствии с вашей целью.
Ссылки:
Вы также можете извлечь вне обратного блока:
render: function() {
var rows = [];
for (var i = 0; i < numrows; i++) {
rows.push(<ObjectRow key={i}/>);
}
return (<tbody>{rows}</tbody>);
}
Просто используйте map метод Array с синтаксисом ES6:
<tbody>
{items.map(item => <ObjectRow key={item.id} name={item.name} />)}
</tbody>
Не забудьте свойство key
.
Функция 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>
Если у вас нет .map()
, вы можете использовать Array.from()
с mapFn
для повторения элементов:
<tbody>
{Array.from({ length: 5 }, (v, k) => <ObjectRow key={k} />)}
</tbody>
Ваш код JSX будет скомпилирован в чистый код JavaScript, любые теги будут заменены объектами ReactElement
. В JavaScript вы не можете вызывать функцию несколько раз для сбора возвращаемых переменных.
Это незаконно, единственный способ - использовать массив для хранения возвращаемых функций.
Или вы можете использовать Array.prototype.map
, который доступен , так как JavaScript ES5 обрабатывает эту ситуацию.
Возможно, мы сможем написать другой компилятор, чтобы воссоздать новый синтаксис JSX для реализации функции повторения, аналогичной Угловой ng-repeat
.
Я знаю, что это старый поток, но вы можете проверить http://wix.github.io/react-templates/ , что позволяет использовать шаблоны jsx-стиля в реакции , с несколькими директивами (например, rt-repeat).
Ваш пример, если вы использовали шаблоны реакции, будет:
<tbody>
<ObjectRow rt-repeat="obj in objects"/>
</tbody>
Я использую это:
gridItems = this.state.applications.map(app =>
<ApplicationItem key={app.Id} app={app } />
);
PD: никогда не забывайте ключ или у вас будет много предупреждений!
.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>
Чтобы циклически повторяться и возвращаться, вы можете достичь этого с помощью from
и map
:
<tbody>
{
Array.from(Array(i)).map(() => <ObjectRow />)
}
</tbody>
, где i = number of times
Просто используйте .map()
для прокрутки вашей коллекции и возврата <ObjectRow>
элементов с реквизитами с каждой итерации.
Предполагая, что objects
является массивом где-то ...
<tbody>
{ objects.map((obj, index) => <ObjectRow obj={ obj } key={ index }/> ) }
</tbody>
, вы можете, конечно, решить с помощью .map, как было предложено другим ответом. Если вы уже используете babel, вы можете подумать об использовании jsx-control-statements Они требуют немного настройки, но я думаю, что это стоит с точки зрения удобочитаемости (особенно для нереактивного разработчика). Если вы используете linter, есть также команды eslint-plugin-jsx-control-statements
, если numrows - это массив, и это очень просто.
<tbody>
{numrows.map(item => <ObjectRow />)}
</tbody>
Тип данных Array в React очень хорош, массив может возвращать новый массив и поддерживать фильтр, уменьшать и т. д.
Если вы уже используете 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>
);
}
}
Вы можете сделать что-то вроде:
let foo = [1,undefined,3]
{ foo.map(e => !!e ? <Object /> : null )}
Вы также можете использовать функцию самозапуска:
return <tbody>
{(() => {
let row = []
for (var i = 0; i < numrows; i++) {
row.push(<ObjectRow key={i} />)
}
return row
})()}
</tbody>
Не уверен, что это сработает для вашей ситуации, но часто 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>
<tbody>{objects.map((o, i) => <ObjectRow obj={o} key={i}/>}</tbody>
с помощью поддержки Reactify ES6 или Babel.
– Steve Taylor
27 July 2015 в 10:24
<ul> {objects.map((object:string,i:number)=>{ return <li>{object}</li> })} </ul>
с использованием TypeScript
– Roberto C Navarro
28 September 2015 в 20:10
for..in
– Damon
15 January 2016 в 20:09
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>
Вот пример из 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 для отличия данных в массиве.
Если у вас еще нет массива на map()
, например, ответа @ FakeRainBrigand, и хотите вставить его таким образом, чтобы исходный макет соответствовал выходному сигналу ближе, чем ответ @ SophieAlpert:
http://plnkr.co/edit/mfqFWODVy8dKQQOkIEGV?p=preview
<tbody>
{[...Array(10)].map((x, i) =>
<ObjectRow key={i} />
)}
</tbody>
Re: указывает, что Array.from
требуется для распространения, но в настоящее время (v5.8.23
), который, похоже, не имеет места при распространении фактического Array
. У меня есть проблема документации , чтобы выяснить это. Но используйте на свой страх и риск или полипол.
Array.apply
<tbody>
{Array.apply(0, Array(10)).map(function (x, i) {
return <ObjectRow key={i} />;
})}
</tbody>
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>
);
}
Array
методы С помощью Array.prototype.fill
вы могли бы сделать это как альтернативу использованию спреда, как показано выше:
<tbody>
{Array(10).fill(1).map((el, i) =>
<ObjectRow key={i} />
)}
</tbody>
(я думаю, вы действительно могли бы опустить любой аргумент fill()
, но я не на это 100%.) Благодаря @FakeRainBrigand для исправления моей ошибки в более ранней версии решения fill()
(см. ревизии).
key
Во всех случаях key
attr устраняет предупреждение с помощью сборки разработки, но недоступно для ребенка. Вы можете передать дополнительный attr, если хотите, чтобы индекс был доступен в дочернем элементе. См. Списки и ключи для обсуждения.
yield
? Нажатие элементов в промежуточную матрицу является отвратительным, когда мы имеем генераторы. Они работают?
– mpen
12 September 2015 в 05:58
[...Array(x)].map(() => <El />))
, которая, по моему мнению, самая элегантная, и почему я ее показал. Re: Второй вопрос, это отличный момент. Кажется, что ничего не происходит в JSX, что исключает его, поэтому это зависит от того, что React или другой потребитель преобразованного JSX делает с дочерними аргументами, о которых я не мог сказать, не глядя на источник. Вы знаете? Это интригующий вопрос.
– JMM
12 September 2015 в 19:49
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>
);
}
Большой вопрос.
Что я делаю, когда хочу добавить определенное количество компонентов, используйте вспомогательную функцию.
Определите функцию, которая возвращает JSX:
const myExample = () => {
let myArray = []
for(let i = 0; i<5;i++) {
myArray.push(<MyComponent/>)
}
return myArray
}
//... in JSX
<tbody>
{myExample()}
</tbody>
map
(например, у вас нет коллекции, хранящейся в переменной). – Kelvin 8 August 2014 в 17:25key
каждому childern. REF: facebook.github.io/react/docs/… – qsun 2 January 2016 в 23:36key
, а также стиль кода, который на самом деле не используется в базовых кодах React. Пожалуйста, рассмотрите этот ответ stackoverflow.com/questions/22876978/loop-inside-react-jsx/… как правильный. – okonetchnikov 31 October 2016 в 15:57