似乎对1个元素总是具有null值

似乎对1个元素总是具有null值

本文介绍了std :: sort函数出现问题.经过2轮迭代,似乎对1个元素总是具有null值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个排序程序,试图对我拥有的数据集进行排序.排序的关键是Grid_ID,它恰好是字母数字数据.我试图据此进行排序

I am trying to write a sort program trying to sort a data set I have. The key to the sorting is Grid_ID and it happened to be an alpha-numeric data. I have tried to sort accordingly

它给我一个错误

在进行调试时,代码的读取部分似乎起作用.将文件内容读取到DataContainer数据中将填充正确的键和文本位置数据.但是当涉及到std :: sort时,当程序"less"被调用时,const GridLabel&第二次迭代后,elem2总是变为零或为空

On doing debugging, the reading part of the code seems to function. The reading of file content into DataContainer data get filled with the right data of key and text position.But when it come to std::sort, when the program "less" is invoked, const GridLabel& elem2 always turn up to be zero or null after 2nd iteration

下面是一些数据集和部分源代码(我在这里不包括按排序顺序写内容,但应该可以运行)

Below is some data set and partial source code (I do not include the write the content in sorted order here but should be runnable)

感谢您的帮助!

这是部分数据集

Grid_Id,Speed,Acc,ID
K31,173,8.37,1
K29,143,3.36,2
K29,107,4.56,3
K30,133,5.97,4
K30,153,2.38,5
J27,203,1.86,6
J27,143,1.59,7
I26,73,7.66,8
I27,134,2.86,9

这是代码

#include <algorithm>
#include <functional>
#include <fstream>
#include <string>

#include <deque>
#include <vector>

#include <iostream>
#include <sstream>

struct GridLabel
{
    std::string key_;
    std::istream::pos_type pos_;        // position in stream where this line starts

    GridLabel( const std::string& key, const std::istream::pos_type& pos) : key_( key)
                                                                   , pos_( pos)
    {
    }

    const GridLabel& operator=( const GridLabel& other)
    {
        key_ = other.key_;
        pos_ = other.pos_;

        return *this;
    }
};

typedef std::vector<  GridLabel> DataContainer;

// Return whether first element is smaller than the second
bool less( const  GridLabel& elem1, const  GridLabel& elem2 )
{
   std::stringstream ss1, ss2;
   ss1 <<  elem1.key_.at(0);
   ss2 <<  elem2.key_.at(0);

   int value  = (ss1.str()).compare(ss2.str());

   if( value < 0 )
   {
       return true;
   }
   else if( value == 0)
   {
       // need to check if the rest are smaller
       std::string substr1 = elem1.key_.substr(1, std::string::npos);
       std::string substr2 = elem2.key_.substr(1, std::string::npos);

       return (std::atoi(substr1.c_str()) < std::atoi(substr2.c_str()));
   }
   else
   {
       return false;
   }
 }

int main(int argc, char* argv[])
{
   DataContainer data;

   // read data into the vector here
   std::ifstream input( "some_file.csv");

   // check if it is correct
   if ( !input.good())
   {
        std::cerr << "Input file can not be openned." << std::endl;
        return -1;
   }

   std::string text;
   std::string key;
   std::istream::pos_type pos;
   int count=0, save=0;

   // to skip the header
   std::getline( input, text);

   for( int line = 0; !input.eof(); ++line)
   {
      // store the position before reading the line
      pos = input.tellg();

      std::getline( input, text);

      // parse it
      save = text.find(",");

      key = text.substr(0,(save));

      data.push_back(  GridLabel( key, pos));
   }

   // sort the data in sorted order
   std::sort( data.begin(), data.end(), less);

   // create the new file
   ...............

   return 0;
}

推荐答案

一个简化的 less()进行比较

  1. GridLabel :: key
  2. 的前几个字符
  3. GridLabel :: key 的2 个字符开始的整数.
  1. the first characters of GridLabel::key
  2. the integral number starting from 2 character of GridLabel::key.

这不会考虑 GridLabel :: key 中还存储了什么.(这可能是OP想要的.)

This will not consider what else is stored in GridLabel::key. (This might be intended by OP.)

示例:

#include <algorithm>
#include <iostream>
#include <string>

struct GridLabel {
  std::string key;
};

bool less(const GridLabel &elem1, const GridLabel &elem2)
{
  // compare first chars of keys
  const char c1 = elem1.key.at(0), c2 = elem2.key.at(0);
  if (c1 != c2) return c1 < c2;
  // compare integral beginning in 2nd char of keys
  const int i1 = atoi(elem1.key.c_str() + 1);
  const int i2 = atoi(elem2.key.c_str() + 1);
  return i1 < i2;
}

int main()
{
  GridLabel data[] = {
    { "K31,173,8.37,1" },
    { "K29,143,3.36,2" },
    { "K29,107,4.56,3" },
    { "K30,133,5.97,4" },
    { "K30,153,2.38,5" },
    { "J27,203,1.86,6" },
    { "J27,143,1.59,7" },
    { "I26,73,7.66,8" },
    { "I27,134,2.86,9" }
  };
  { std::cout << "Original data:\n";
    int i = 0;
    for (const GridLabel &entry : data) {
      std::cout << i++ << ": '" << entry.key << "'\n";
    }
  }
  std::cout << "Sorting...";
  std::sort(std::begin(data), std::end(data), less);
  std::cout << " Done.\n";
  { std::cout << "Sorted data:\n";
    int i = 0;
    for (const GridLabel &entry : data) {
      std::cout << i++ << ": '" << entry.key << "'\n";
    }
  }
}

输出:

Original data:
0: 'K31,173,8.37,1'
1: 'K29,143,3.36,2'
2: 'K29,107,4.56,3'
3: 'K30,133,5.97,4'
4: 'K30,153,2.38,5'
5: 'J27,203,1.86,6'
6: 'J27,143,1.59,7'
7: 'I26,73,7.66,8'
8: 'I27,134,2.86,9'
Sorting... Done.
Sorted data:
0: 'I26,73,7.66,8'
1: 'I27,134,2.86,9'
2: 'J27,203,1.86,6'
3: 'J27,143,1.59,7'
4: 'K29,143,3.36,2'
5: 'K29,107,4.56,3'
6: 'K30,133,5.97,4'
7: 'K30,153,2.38,5'
8: 'K31,173,8.37,1'

coliru上的实时演示

请注意(根据谓词 less()的实现方式),有很多元素被认为是相等的:

Please, note that (according to how predicate less() is implemented) there are a lot elements which are considered as equal:

  • I26,73,7.66,8 I27,134,2.86,9
  • J27,203,1.86,6 J27,143,1.59,7

这些元素在排序后将以任意顺序出现.

These elements will appear in abitrary order after sorting.

或者, std :: stable_sort() 保留原始顺序.

Alternatively, std::stable_sort() could be used which will preserve the original order in these cases.

这篇关于std :: sort函数出现问题.经过2轮迭代,似乎对1个元素总是具有null值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!