Rolland
Rolland

Reputation: 687

How to get repeated values sequently on a html table with jQuery, by condition

I'm trying to determine how many times a number was repeated in a table row, sequently. When 3 or more occurrences is found, I need change the color of td to red, like this:

Expected result:

Expected result

My regex is working, but I cannot to get the correct repeat count and change the td's color....

x = $("table").find("tr");
text = "";

x.each(function(line){
  number = $(this).text();
  check = checkNum(number);
  console.log(checkNum(number));

  if(check.length > 0){
    repeats = check[0][1];
    text += "Number "+number[check[0]['index']]+" was repeated "+repeats+ " times on line "+line+"<br>";
    $('#results').html(text);
    $(this).css('color', 'red');
  }
});

function checkNum(num) {
    var tempArray = [];
    num = num.replace(/\s+/g,"_");
    exp = new RegExp(/([0-9])\1{2,}/, "g");
    ex = exp.exec(num);

    if(ex){
     tempArray.push(ex);
    }

    return tempArray;
}

Please check this fiddle

Upvotes: 6

Views: 1201

Answers (3)

Daerik
Daerik

Reputation: 4277

Not very pretty, but it will give you your desired result. I'm using HTML data-* Attributes to group the numbers together.

/* Variable Defaults */
var objectContainer = {};
var index;

/* Loop Through Rows / Cells */
$('tr').find('td').each(function() {
    $(this).attr('data-text', $(this).text());
}).end().each(function() {
    index = $(this).index();
    objectContainer[index] = {};
    $(this).find('td').each(function() {
        objectContainer[index][$(this).data('text')] = $(this).siblings('td[data-text="' + $(this).data('text') + '"]').length + 1;
    });
});

/* Iterate Object Container */
$.each(objectContainer, function(row, data) {
    $.each(data, function(key, value) {
        if(value >= 3) {
            $('tr:eq(' + row + ')').find('td[data-text="' + key + '"]').css('color', 'red');
            $('#results').append($('<span/>', {
                text: 'Number ' + key + ' was repeated ' + value + ' times on line ' + row + '.'
            })).append($('<br/>'));
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr>
        <td>2</td>
        <td>3</td>
        <td>1</td>
        <td>5</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>1</td>
        <td>0</td>
    </tr>
    <tr>
        <td>0</td>
        <td>5</td>
        <td>1</td>
        <td>1</td>
        <td>8</td>
        <td>3</td>
        <td>3</td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>0</td>
        <td>4</td>
        <td>1</td>
        <td>5</td>
        <td>8</td>
        <td>7</td>
        <td>6</td>
        <td>3</td>
        <td>4</td>
    </tr>
    <tr>
        <td>5</td>
        <td>2</td>
        <td>2</td>
        <td>2</td>
        <td>2</td>
        <td>9</td>
        <td>2</td>
        <td>2</td>
        <td>0</td>
    </tr>
    <tr>
        <td>1</td>
        <td>4</td>
        <td>4</td>
        <td>4</td>
        <td>2</td>
        <td>4</td>
        <td>4</td>
        <td>4</td>
        <td>4</td>
    </tr>
</table>
<div id="results">
</div>

Upvotes: 1

trincot
trincot

Reputation: 350375

Here is functional way to do it (without regular expressions):

$("#results").html(
    [].concat.apply(
        $.map($("table tr"), function(tr, line){
            return $(tr).children().get().reduceRight(function (acc, td, i) {
                var txt = $(td).text();
                if (txt === acc[0][0]) 
                    acc[0][1] = i; // Extend range
                else
                    acc.unshift([txt, i, i+1]); // Add a new range
                return acc;
            }, [[null, 0, 0]])
            .filter(function (range) { // Get the ranges that are long enough
                return range[2] - range[1] >= 3;
            })
            .map(function (range) { // Map them to strings, and apply the styling
                $(tr).children().slice(range[1], range[2]).css('color', 'red');
                return "Number "+range[0]+" was repeated "+(range[2] - range[1])+ " times on line "+line;
            })
        })
    ).join("<br>")
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr><td>2</td><td>3</td><td>1</td><td>5</td><td>1</td><td>1</td><td>1</td><td>1</td><td>0</td></tr>
<tr><td>0</td><td>5</td><td>1</td><td>1</td><td>8</td><td>3</td><td>3</td><td>3</td><td>4</td></tr>
<tr><td>0</td><td>4</td><td>1</td><td>5</td><td>8</td><td>7</td><td>6</td><td>3</td><td>4</td></tr>
<tr><td>5</td><td>2</td><td>2</td><td>2</td><td>2</td><td>9</td><td>2</td><td>2</td><td>0</td></tr>
<tr><td>1</td><td>4</td><td>4</td><td>4</td><td>2</td><td>4</td><td>4</td><td>4</td><td>4</td></tr>

</table>
<div id='results'>
</div>

Upvotes: 2

Callam
Callam

Reputation: 11539

By parsing the table into an array of each row as a concatenated string, you can execute your regular expression on the row and apply the necessary CSS to a slice of the children in that row using the substring range returned by the regular expression.

$("table").find("tr").each(function (line, row) {

    var children = $(row).children("td");
    var numbers = children.map(function (_, data) {
        return data.innerHTML;
    });

    var expression = new RegExp(/([0-9])\1{2,}/, "g");
    var string = numbers.get().join('');
    var result = expression.exec(string);

    while (result) {

        var length = result[0].length;
        var number = result[1];
        var start = result.index;
        var end = start + length;

        children.slice(start, end).each(function (_, child) {
            $(child).css('color', 'red');
        });

        $("#results").append(
            '<span>Number ' + number + 
            ' was repeated ' + length + 
            ' times on line ' + line + '.' +
            '</span><br>'
        );

        result = expression.exec(string);
    }
});

https://jsfiddle.net/ews8t955/1/

Upvotes: 1

Related Questions